通过本篇文章,让你掌握新的技巧,请不用只看看一点,希望能够看完,让你很快明白不同的使用场景
ListView 和 Adapter 的基础
工作原理:
- ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。
- 一个新的视图被返回并显示
如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!
实际上Android为你缓存了视图。
Android中有个叫做Recycler的构件,下图是他的工作原理:

- 如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。
- ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。
- 当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。
请看下面的示例代码,这里在getView中使用了System.out进行输出
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1
</div>
<div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
<div class="line number18 index17 alt1">
18
</div>
<div class="line number19 index18 alt2">
19
</div>
<div class="line number20 index19 alt1">
20
</div>
<div class="line number21 index20 alt2">
21
</div>
<div class="line number22 index21 alt1">
22
</div>
<div class="line number23 index22 alt2">
23
</div>
<div class="line number24 index23 alt1">
24
</div>
<div class="line number25 index24 alt2">
25
</div>
<div class="line number26 index25 alt1">
26
</div>
<div class="line number27 index26 alt2">
27
</div>
<div class="line number28 index27 alt1">
28
</div>
<div class="line number29 index28 alt2">
29
</div>
<div class="line number30 index29 alt1">
30
</div>
<div class="line number31 index30 alt2">
31
</div>
<div class="line number32 index31 alt1">
32
</div>
<div class="line number33 index32 alt2">
33
</div>
<div class="line number34 index33 alt1">
34
</div>
<div class="line number35 index34 alt2">
35
</div>
<div class="line number36 index35 alt1">
36
</div>
<div class="line number37 index36 alt2">
37
</div>
<div class="line number38 index37 alt1">
38
</div>
<div class="line number39 index38 alt2">
39
</div>
<div class="line number40 index39 alt1">
40
</div>
<div class="line number41 index40 alt2">
41
</div>
<div class="line number42 index41 alt1">
42
</div>
<div class="line number43 index42 alt2">
43
</div>
<div class="line number44 index43 alt1">
44
</div>
<div class="line number45 index44 alt2">
45
</div>
<div class="line number46 index45 alt1">
46
</div>
<div class="line number47 index46 alt2">
47
</div>
<div class="line number48 index47 alt1">
48
</div>
<div class="line number49 index48 alt2">
49
</div>
<div class="line number50 index49 alt1">
50
</div>
<div class="line number51 index50 alt2">
51
</div>
<div class="line number52 index51 alt1">
52
</div>
<div class="line number53 index52 alt2">
53
</div>
<div class="line number54 index53 alt1">
54
</div>
<div class="line number55 index54 alt2">
55
</div>
<div class="line number56 index55 alt1">
56
</div>
<div class="line number57 index56 alt2">
57
</div>
<div class="line number58 index57 alt1">
58
</div>
<div class="line number59 index58 alt2">
59
</div>
<div class="line number60 index59 alt1">
60
</div>
<div class="line number61 index60 alt2">
61
</div>
<div class="line number62 index61 alt1">
62
</div>
<div class="line number63 index62 alt2">
63
</div>
<div class="line number64 index63 alt1">
64
</div>
<div class="line number65 index64 alt2">
65
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`public` `class` `MultipleItemsListextends ListActivity {`
</div>
<div class="line number2 index1 alt1">
` `
</div>
<div class="line number3 index2 alt2">
` ``private` `MyCustomAdapter mAdapter;`
</div>
<div class="line number4 index3 alt1">
` `
</div>
<div class="line number5 index4 alt2">
` ``@Override`
</div>
<div class="line number6 index5 alt1">
` ``public` `void` `onCreate(Bundle savedInstanceState) {`
</div>
<div class="line number7 index6 alt2">
` ``super``.onCreate(savedInstanceState);`
</div>
<div class="line number8 index7 alt1">
` ``mAdapter = ``new` `MyCustomAdapter();`
</div>
<div class="line number9 index8 alt2">
` ``for` `(``int` `i = ````; i < ``50``; i++) {`
</div>
<div class="line number10 index9 alt1">
` ``mAdapter.addItem(``"item "` `+ i);`
</div>
<div class="line number11 index10 alt2">
` ``}`
</div>
<div class="line number12 index11 alt1">
` ``setListAdapter(mAdapter);`
</div>
<div class="line number13 index12 alt2">
` ``}`
</div>
<div class="line number14 index13 alt1">
` `
</div>
<div class="line number15 index14 alt2">
` ``private` `class` `MyCustomAdapterextends BaseAdapter {`
</div>
<div class="line number16 index15 alt1">
` `
</div>
<div class="line number17 index16 alt2">
` ``private` `ArrayList mData = ``new` `ArrayList();`
</div>
<div class="line number18 index17 alt1">
` ``private` `LayoutInflater mInflater;`
</div>
<div class="line number19 index18 alt2">
` `
</div>
<div class="line number20 index19 alt1">
` ``public` `MyCustomAdapter() {`
</div>
<div class="line number21 index20 alt2">
` ``mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);`
</div>
<div class="line number22 index21 alt1">
` ``}`
</div>
<div class="line number23 index22 alt2">
` `
</div>
<div class="line number24 index23 alt1">
` ``public` `void` `addItem(``final` `String item) {`
</div>
<div class="line number25 index24 alt2">
` ``mData.add(item);`
</div>
<div class="line number26 index25 alt1">
` ``notifyDataSetChanged();`
</div>
<div class="line number27 index26 alt2">
` ``}`
</div>
<div class="line number28 index27 alt1">
` `
</div>
<div class="line number29 index28 alt2">
` ``@Override`
</div>
<div class="line number30 index29 alt1">
` ``public` `int` `getCount() {`
</div>
<div class="line number31 index30 alt2">
` ``return` `mData.size();`
</div>
<div class="line number32 index31 alt1">
` ``}`
</div>
<div class="line number33 index32 alt2">
` `
</div>
<div class="line number34 index33 alt1">
` ``@Override`
</div>
<div class="line number35 index34 alt2">
` ``public` `String getItem(``int` `position) {`
</div>
<div class="line number36 index35 alt1">
` ``return` `mData.get(position);`
</div>
<div class="line number37 index36 alt2">
` ``}`
</div>
<div class="line number38 index37 alt1">
` `
</div>
<div class="line number39 index38 alt2">
` ``@Override`
</div>
<div class="line number40 index39 alt1">
` ``public` `long` `getItemId(``int` `position) {`
</div>
<div class="line number41 index40 alt2">
` ``return` `position;`
</div>
<div class="line number42 index41 alt1">
` ``}`
</div>
<div class="line number43 index42 alt2">
` `
</div>
<div class="line number44 index43 alt1">
` ``@Override`
</div>
<div class="line number45 index44 alt2">
` ``public` `View getView(``int` `position, View convertView, ViewGroup parent) {`
</div>
<div class="line number46 index45 alt1">
` ``System.out.println(``"getView "` `+ position + ``" "` `+ convertView);`
</div>
<div class="line number47 index46 alt2">
` ``ViewHolder holder = ``null``;`
</div>
<div class="line number48 index47 alt1">
` ``if` `(convertView == ``null``) {`
</div>
<div class="line number49 index48 alt2">
` ``convertView = mInflater.inflate(R.layout.item1, ``null``);`
</div>
<div class="line number50 index49 alt1">
` ``holder = ``new` `ViewHolder();`
</div>
<div class="line number51 index50 alt2">
` ``holder.textView = (TextView)convertView.findViewById(R.id.text);`
</div>
<div class="line number52 index51 alt1">
` ``convertView.setTag(holder);`
</div>
<div class="line number53 index52 alt2">
` ``}``else` `{`
</div>
<div class="line number54 index53 alt1">
` ``holder = (ViewHolder)convertView.getTag();`
</div>
<div class="line number55 index54 alt2">
` ``}`
</div>
<div class="line number56 index55 alt1">
` ``holder.textView.setText(mData.get(position));`
</div>
<div class="line number57 index56 alt2">
` ``return` `convertView;`
</div>
<div class="line number58 index57 alt1">
` ``}`
</div>
<div class="line number59 index58 alt2">
` `
</div>
<div class="line number60 index59 alt1">
` ``}`
</div>
<div class="line number61 index60 alt2">
` `
</div>
<div class="line number62 index61 alt1">
` ``public` `static` `class` `ViewHolder {`
</div>
<div class="line number63 index62 alt2">
` ``public` `TextView textView;`
</div>
<div class="line number64 index63 alt1">
` ``}`
</div>
<div class="line number65 index64 alt2">
`}`
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
执行程序,然后在Logcat中查看日志

getView 被调用 9 次 ,convertView 对于所有的可见项目是空值(如下)
- 02-05 13:47:32.559: INFO/System.out(947): getView 0 null
- 02-05 13:47:32.570: INFO/System.out(947): getView 1 null
- 02-05 13:47:32.589: INFO/System.out(947): getView 2 null
- 02-05 13:47:32.599: INFO/System.out(947): getView 3 null
- 02-05 13:47:32.619: INFO/System.out(947): getView 4 null
- 02-05 13:47:32.629: INFO/System.out(947): getView 5 null
- 02-05 13:47:32.708: INFO/System.out(947): getView 6 null
- 02-05 13:47:32.719: INFO/System.out(947): getView 7 null
- 02-05 13:47:32.729: INFO/System.out(947): getView 8 null
然后稍微向下滚动List,直到item10出现:

convertView仍然是空值,因为recycler中没有视图(item1的边缘仍然可见,在顶端)
<div>
<div>
<div>
**[java]** [view plain](http://blog.csdn.net/droyon/article/details/10008277#)[copy](http://blog.csdn.net/droyon/article/details/10008277#)
</div>
</div>
- 02-05 13:48:25.169: INFO/System.out(947): getView 9 null
</div>
</div>
再滚动List

convertView不是空值了!item1离开屏幕到Recycler中去了,然后item11被创建
<div>
<div>
<div>
**[java]** [view plain](http://blog.csdn.net/droyon/article/details/10008277#)[copy](http://blog.csdn.net/droyon/article/details/10008277#)
</div>
</div>
- 02-05 13:48:42.879: INFO/System.out(947): getView 10 android.widget.LinearLayout@437430f8
</div>
</div>
再滚动:
<div>
<div>
<div>
**[java]** [view plain](http://blog.csdn.net/droyon/article/details/10008277#)[copy](http://blog.csdn.net/droyon/article/details/10008277#)
</div>
</div>
- 02-05 14:01:31.069: INFO/System.out(947): getView 11 android.widget.LinearLayout@437447d0
- 02-05 14:01:31.142: INFO/System.out(947): getView 12 android.widget.LinearLayout@43744ff8
- 02-05 14:01:31.279: INFO/System.out(947): getView 13 android.widget.LinearLayout@43743fa8
- 02-05 14:01:31.350: INFO/System.out(947): getView 14 android.widget.LinearLayout@43745820
- 02-05 14:01:31.429: INFO/System.out(947): getView 15 android.widget.LinearLayout@43746048
- 02-05 14:01:31.550: INFO/System.out(947): getView 16 android.widget.LinearLayout@43746870
- 02-05 14:01:31.669: INFO/System.out(947): getView 17 android.widget.LinearLayout@43747098
- 02-05 14:01:31.839: INFO/System.out(947): getView 18 android.widget.LinearLayout@437478c0
- 02-05 14:03:30.900: INFO/System.out(947): getView 19 android.widget.LinearLayout@43748df0
- 02-05 14:03:32.069: INFO/System.out(947): getView 20 android.widget.LinearLayout@437430f8
</div>
</div>
convertView 如我们所期待的非空了,在item11离开屏幕之后,它的视图(@437430f8)作为convertView容纳item21了
不同的项目布局(item layout)
我们再举一个稍微复杂的例子,在上例的list中加入一些分隔线
你需要做这些:
- 重(@Override)写 getViewTypeCount() – 返回你有多少个不同的布局
- 重写 getItemViewType(int) – 由position返回view type id
- 根据view item的类型,在getView中创建正确的convertView
以下是代码:
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1
</div>
<div class="line number2 index1 alt1">
2
</div>
<div class="line number3 index2 alt2">
3
</div>
<div class="line number4 index3 alt1">
4
</div>
<div class="line number5 index4 alt2">
5
</div>
<div class="line number6 index5 alt1">
6
</div>
<div class="line number7 index6 alt2">
7
</div>
<div class="line number8 index7 alt1">
8
</div>
<div class="line number9 index8 alt2">
9
</div>
<div class="line number10 index9 alt1">
10
</div>
<div class="line number11 index10 alt2">
11
</div>
<div class="line number12 index11 alt1">
12
</div>
<div class="line number13 index12 alt2">
13
</div>
<div class="line number14 index13 alt1">
14
</div>
<div class="line number15 index14 alt2">
15
</div>
<div class="line number16 index15 alt1">
16
</div>
<div class="line number17 index16 alt2">
17
</div>
<div class="line number18 index17 alt1">
18
</div>
<div class="line number19 index18 alt2">
19
</div>
<div class="line number20 index19 alt1">
20
</div>
<div class="line number21 index20 alt2">
21
</div>
<div class="line number22 index21 alt1">
22
</div>
<div class="line number23 index22 alt2">
23
</div>
<div class="line number24 index23 alt1">
24
</div>
<div class="line number25 index24 alt2">
25
</div>
<div class="line number26 index25 alt1">
26
</div>
<div class="line number27 index26 alt2">
27
</div>
<div class="line number28 index27 alt1">
28
</div>
<div class="line number29 index28 alt2">
29
</div>
<div class="line number30 index29 alt1">
30
</div>
<div class="line number31 index30 alt2">
31
</div>
<div class="line number32 index31 alt1">
32
</div>
<div class="line number33 index32 alt2">
33
</div>
<div class="line number34 index33 alt1">
34
</div>
<div class="line number35 index34 alt2">
35
</div>
<div class="line number36 index35 alt1">
36
</div>
<div class="line number37 index36 alt2">
37
</div>
<div class="line number38 index37 alt1">
38
</div>
<div class="line number39 index38 alt2">
39
</div>
<div class="line number40 index39 alt1">
40
</div>
<div class="line number41 index40 alt2">
41
</div>
<div class="line number42 index41 alt1">
42
</div>
<div class="line number43 index42 alt2">
43
</div>
<div class="line number44 index43 alt1">
44
</div>
<div class="line number45 index44 alt2">
45
</div>
<div class="line number46 index45 alt1">
46
</div>
<div class="line number47 index46 alt2">
47
</div>
<div class="line number48 index47 alt1">
48
</div>
<div class="line number49 index48 alt2">
49
</div>
<div class="line number50 index49 alt1">
50
</div>
<div class="line number51 index50 alt2">
51
</div>
<div class="line number52 index51 alt1">
52
</div>
<div class="line number53 index52 alt2">
53
</div>
<div class="line number54 index53 alt1">
54
</div>
<div class="line number55 index54 alt2">
55
</div>
<div class="line number56 index55 alt1">
56
</div>
<div class="line number57 index56 alt2">
57
</div>
<div class="line number58 index57 alt1">
58
</div>
<div class="line number59 index58 alt2">
59
</div>
<div class="line number60 index59 alt1">
60
</div>
<div class="line number61 index60 alt2">
61
</div>
<div class="line number62 index61 alt1">
62
</div>
<div class="line number63 index62 alt2">
63
</div>
<div class="line number64 index63 alt1">
64
</div>
<div class="line number65 index64 alt2">
65
</div>
<div class="line number66 index65 alt1">
66
</div>
<div class="line number67 index66 alt2">
67
</div>
<div class="line number68 index67 alt1">
68
</div>
<div class="line number69 index68 alt2">
69
</div>
<div class="line number70 index69 alt1">
70
</div>
<div class="line number71 index70 alt2">
71
</div>
<div class="line number72 index71 alt1">
72
</div>
<div class="line number73 index72 alt2">
73
</div>
<div class="line number74 index73 alt1">
74
</div>
<div class="line number75 index74 alt2">
75
</div>
<div class="line number76 index75 alt1">
76
</div>
<div class="line number77 index76 alt2">
77
</div>
<div class="line number78 index77 alt1">
78
</div>
<div class="line number79 index78 alt2">
79
</div>
<div class="line number80 index79 alt1">
80
</div>
<div class="line number81 index80 alt2">
81
</div>
<div class="line number82 index81 alt1">
82
</div>
<div class="line number83 index82 alt2">
83
</div>
<div class="line number84 index83 alt1">
84
</div>
<div class="line number85 index84 alt2">
85
</div>
<div class="line number86 index85 alt1">
86
</div>
<div class="line number87 index86 alt2">
87
</div>
<div class="line number88 index87 alt1">
88
</div>
<div class="line number89 index88 alt2">
89
</div>
<div class="line number90 index89 alt1">
90
</div>
<div class="line number91 index90 alt2">
91
</div>
<div class="line number92 index91 alt1">
92
</div>
<div class="line number93 index92 alt2">
93
</div>
<div class="line number94 index93 alt1">
94
</div>
<div class="line number95 index94 alt2">
95
</div>
<div class="line number96 index95 alt1">
96
</div>
<div class="line number97 index96 alt2">
97
</div>
<div class="line number98 index97 alt1">
98
</div>
<div class="line number99 index98 alt2">
99
</div>
<div class="line number100 index99 alt1">
100
</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
`public` `class` `MultipleItemsListextends ListActivity {`
</div>
<div class="line number2 index1 alt1">
` `
</div>
<div class="line number3 index2 alt2">
` ``private` `MyCustomAdapter mAdapter;`
</div>
<div class="line number4 index3 alt1">
` `
</div>
<div class="line number5 index4 alt2">
` ``@Override`
</div>
<div class="line number6 index5 alt1">
` ``public` `void` `onCreate(Bundle savedInstanceState) {`
</div>
<div class="line number7 index6 alt2">
` ``super``.onCreate(savedInstanceState);`
</div>
<div class="line number8 index7 alt1">
` ``mAdapter = ``new` `MyCustomAdapter();`
</div>
<div class="line number9 index8 alt2">
` ``for` `(``int` `i = ``1``; i < ``50``; i++) {`
</div>
<div class="line number10 index9 alt1">
` ``mAdapter.addItem(``"item "` `+ i);`
</div>
<div class="line number11 index10 alt2">
` ``if` `(i % ``4` `==````) {`
</div>
<div class="line number12 index11 alt1">
` ``mAdapter.addSeparatorItem(``"separator "` `+ i);`
</div>
<div class="line number13 index12 alt2">
` ``}`
</div>
<div class="line number14 index13 alt1">
` ``}`
</div>
<div class="line number15 index14 alt2">
` ``setListAdapter(mAdapter);`
</div>
<div class="line number16 index15 alt1">
` ``}`
</div>
<div class="line number17 index16 alt2">
` `
</div>
<div class="line number18 index17 alt1">
` ``private` `class` `MyCustomAdapterextends BaseAdapter {`
</div>
<div class="line number19 index18 alt2">
` `
</div>
<div class="line number20 index19 alt1">
` ``private` `static` `final` `int` `TYPE_ITEM = ````;`
</div>
<div class="line number21 index20 alt2">
` ``private` `static` `final` `int` `TYPE_SEPARATOR = ``1``;`
</div>
<div class="line number22 index21 alt1">
` ``private` `static` `final` `int` `TYPE_MAX_COUNT = TYPE_SEPARATOR + ``1``;`
</div>
<div class="line number23 index22 alt2">
` `
</div>
<div class="line number24 index23 alt1">
` ``private` `ArrayList mData = ``new` `ArrayList();`
</div>
<div class="line number25 index24 alt2">
` ``private` `LayoutInflater mInflater;`
</div>
<div class="line number26 index25 alt1">
` `
</div>
<div class="line number27 index26 alt2">
` ``private` `TreeSet mSeparatorsSet = ``new` `TreeSet();`
</div>
<div class="line number28 index27 alt1">
` `
</div>
<div class="line number29 index28 alt2">
` ``public` `MyCustomAdapter() {`
</div>
<div class="line number30 index29 alt1">
` ``mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);`
</div>
<div class="line number31 index30 alt2">
` ``}`
</div>
<div class="line number32 index31 alt1">
` `
</div>
<div class="line number33 index32 alt2">
` ``public` `void` `addItem(``final` `String item) {`
</div>
<div class="line number34 index33 alt1">
` ``mData.add(item);`
</div>
<div class="line number35 index34 alt2">
` ``notifyDataSetChanged();`
</div>
<div class="line number36 index35 alt1">
` ``}`
</div>
<div class="line number37 index36 alt2">
` `
</div>
<div class="line number38 index37 alt1">
` ``public` `void` `addSeparatorItem(``final` `String item) {`
</div>
<div class="line number39 index38 alt2">
` ``mData.add(item);`
</div>
<div class="line number40 index39 alt1">
` ``// save separator position`
</div>
<div class="line number41 index40 alt2">
` ``mSeparatorsSet.add(mData.size() - ``1``);`
</div>
<div class="line number42 index41 alt1">
` ``notifyDataSetChanged();`
</div>
<div class="line number43 index42 alt2">
` ``}`
</div>
<div class="line number44 index43 alt1">
` `
</div>
<div class="line number45 index44 alt2">
` ``@Override`
</div>
<div class="line number46 index45 alt1">
` ``public` `int` `getItemViewType(``int` `position) {`
</div>
<div class="line number47 index46 alt2">
` ``return` `mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;`
</div>
<div class="line number48 index47 alt1">
` ``}`
</div>
<div class="line number49 index48 alt2">
` `
</div>
<div class="line number50 index49 alt1">
` ``@Override`
</div>
<div class="line number51 index50 alt2">
` ``public` `int` `getViewTypeCount() {`
</div>
<div class="line number52 index51 alt1">
` ``return` `TYPE_MAX_COUNT;`
</div>
<div class="line number53 index52 alt2">
` ``}`
</div>
<div class="line number54 index53 alt1">
` `
</div>
<div class="line number55 index54 alt2">
` ``@Override`
</div>
<div class="line number56 index55 alt1">
` ``public` `int` `getCount() {`
</div>
<div class="line number57 index56 alt2">
` ``return` `mData.size();`
</div>
<div class="line number58 index57 alt1">
` ``}`
</div>
<div class="line number59 index58 alt2">
` `
</div>
<div class="line number60 index59 alt1">
` ``@Override`
</div>
<div class="line number61 index60 alt2">
` ``public` `String getItem(``int` `position) {`
</div>
<div class="line number62 index61 alt1">
` ``return` `mData.get(position);`
</div>
<div class="line number63 index62 alt2">
` ``}`
</div>
<div class="line number64 index63 alt1">
` `
</div>
<div class="line number65 index64 alt2">
` ``@Override`
</div>
<div class="line number66 index65 alt1">
` ``public` `long` `getItemId(``int` `position) {`
</div>
<div class="line number67 index66 alt2">
` ``return` `position;`
</div>
<div class="line number68 index67 alt1">
` ``}`
</div>
<div class="line number69 index68 alt2">
` `
</div>
<div class="line number70 index69 alt1">
` ``@Override`
</div>
<div class="line number71 index70 alt2">
` ``public` `View getView(``int` `position, View convertView, ViewGroup parent) {`
</div>
<div class="line number72 index71 alt1">
` ``ViewHolder holder = ``null``;`
</div>
<div class="line number73 index72 alt2">
` ``int` `type = getItemViewType(position);`
</div>
<div class="line number74 index73 alt1">
` ``System.out.println(``"getView "` `+ position + ``" "` `+ convertView + ``" type = "` `+ type);`
</div>
<div class="line number75 index74 alt2">
` ``if` `(convertView == ``null``) {`
</div>
<div class="line number76 index75 alt1">
` ``holder = ``new` `ViewHolder();`
</div>
<div class="line number77 index76 alt2">
` ``switch` `(type) {`
</div>
<div class="line number78 index77 alt1">
` ``case` `TYPE_ITEM:`
</div>
<div class="line number79 index78 alt2">
` ``convertView = mInflater.inflate(R.layout.item1, ``null``);`
</div>
<div class="line number80 index79 alt1">
` ``holder.textView = (TextView)convertView.findViewById(R.id.text);`
</div>
<div class="line number81 index80 alt2">
` ``break``;`
</div>
<div class="line number82 index81 alt1">
` ``case` `TYPE_SEPARATOR:`
</div>
<div class="line number83 index82 alt2">
` ``convertView = mInflater.inflate(R.layout.item2, ``null``);`
</div>
<div class="line number84 index83 alt1">
` ``holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);`
</div>
<div class="line number85 index84 alt2">
` ``break``;`
</div>
<div class="line number86 index85 alt1">
` ``}`
</div>
<div class="line number87 index86 alt2">
` ``convertView.setTag(holder);`
</div>
<div class="line number88 index87 alt1">
` ``}``else` `{`
</div>
<div class="line number89 index88 alt2">
` ``holder = (ViewHolder)convertView.getTag();`
</div>
<div class="line number90 index89 alt1">
` ``}`
</div>
<div class="line number91 index90 alt2">
` ``holder.textView.setText(mData.get(position));`
</div>
<div class="line number92 index91 alt1">
` ``return` `convertView;`
</div>
<div class="line number93 index92 alt2">
` ``}`
</div>
<div class="line number94 index93 alt1">
` `
</div>
<div class="line number95 index94 alt2">
` ``}`
</div>
<div class="line number96 index95 alt1">
` `
</div>
<div class="line number97 index96 alt2">
` ``public` `static` `class` `ViewHolder {`
</div>
<div class="line number98 index97 alt1">
` ``public` `TextView textView;`
</div>
<div class="line number99 index98 alt2">
` ``}`
</div>
<div class="line number100 index99 alt1">
`}`
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
运行程序,你会看到每4个item一个分割线

看看日志,无异常,所有的convertView都是空的
<div>
<div>
<div>
**[java]** [view plain](http://blog.csdn.net/droyon/article/details/10008277#)[copy](http://blog.csdn.net/droyon/article/details/10008277#)
</div>
</div>
- 02-05 15:19:03.080: INFO/System.out(1035): getView 0 null type = 0
- 02-05 15:19:03.112: INFO/System.out(1035): getView 1 null type = 0
- 02-05 15:19:03.130: INFO/System.out(1035): getView 2 null type = 0
- 02-05 15:19:03.141: INFO/System.out(1035): getView 3 null type = 0
- 02-05 15:19:03.160: INFO/System.out(1035): getView 4 null type = 1
- 02-05 15:19:03.170: INFO/System.out(1035): getView 5 null type = 0
- 02-05 15:19:03.180: INFO/System.out(1035): getView 6 null type = 0
- 02-05 15:19:03.190: INFO/System.out(1035): getView 7 null type = 0
- 02-05 15:19:03.210: INFO/System.out(1035): getView 8 null type = 0
- 02-05 15:19:03.210: INFO/System.out(1035): getView 9 null type = 1
</div>
</div>
滚动list:
<div>
<div>
<div>
**[java]** [view plain](http://blog.csdn.net/droyon/article/details/10008277#)[copy](http://blog.csdn.net/droyon/article/details/10008277#)
</div>
</div>
- 02-05 15:19:54.160: INFO/System.out(1035): getView 10 null type = 0
- 02-05 15:19:57.440: INFO/System.out(1035): getView 11 android.widget.LinearLayout@43744528 type = 0
- 02-05 15:20:01.310: INFO/System.out(1035): getView 12 android.widget.LinearLayout@43744eb0 type = 0
- 02-05 15:20:01.880: INFO/System.out(1035): getView 13 android.widget.LinearLayout@437456d8 type = 0
- 02-05 15:20:02.869: INFO/System.out(1035): getView 14 null type = 1
- 02-05 15:20:06.489: INFO/System.out(1035): getView 15 android.widget.LinearLayout@43745f00 type = 0
- 02-05 15:20:07.749: INFO/System.out(1035): getView 16 android.widget.LinearLayout@43747170 type = 0
- 02-05 15:20:10.250: INFO/System.out(1035): getView 17 android.widget.LinearLayout@43747998 type = 0
- 02-05 15:20:11.661: INFO/System.out(1035): getView 18 android.widget.LinearLayout@437481c0 type = 0
- 02-05 15:20:13.180: INFO/System.out(1035): getView 19 android.widget.LinearLayout@437468a0 type = 1
- 02-05 15:20:16.900: INFO/System.out(1035): getView 20 android.widget.LinearLayout@437489e8 type = 0
- 02-05 15:20:25.690: INFO/System.out(1035): getView 21 android.widget.LinearLayout@4374a8d8 type = 0
</div>
</div>
convertView对于分割线是空的,直到第一个分割线可见,当其离开屏幕,视图去到Recycler并且convertView开始起作用。
转自:http://www.aitinan.com/3885.html
Android高手进阶:Adapter深入理解与优化
一般是针对包含多个元素的View,如ListView,GridView,ExpandableListview,的时候我们是给其设置一个Adapter。Adapter是与View之间提供数据的桥梁,也是提供每个Item的视图桥梁。
以ListView为例,其工作原理为:
● ListView针对List中每个item, adapter都会调用一个getView的方法获得布局视图
●我们一般会Inflate一个新的View,填充数据并返回显示
当然如果我们的Item很多话(比如上万个),都会新建一个View吗?很明显这样内存是接受不了的,Google也不会这么做,Android中有个叫做Recycler的构件,下图是他的工作原理:
很明显,无论数据中是多少个item,在显示上Recycler只存储其中可见的View在内存中。当向下滑动时,顶部不可见Item直接回移动到下方再次填充数据变为新增项。这样就不用每次都新建一个View了。
这个也就是我们在Adapter中常见的getView方法的调用,对应此方法我们就能看出,convertView就是每一Item在Recyler之前的布局视图。
- public View getView(int position, View convertView, ViewGrouppare
所以,Android已经给我们提供了Recycler机制了,我们就应该利用此机制,而不是每次都去inflate一个View。
Example
Don’t
public View getView(int position, View convertView, ViewGroupparent){
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_view,null);
//dosomething…
return converView;
}
Do
public View getView(int position, View convertView, ViewGroupparent){
if (convertView ==null) {
convertView =LayoutInflater.from(mContext).inflate(R.layout.item_view, null);
}
//dosomething…
return converView;
}
ViewHolder的作用
之前所说的Recycler模式是为了解决重复inflate时候造成的View资源浪费,还哪有什么方法何可再次优化我们的性能吗?答案是Yes。
我们还是从getView中的每一个方法调用去查看,发现其实我们拿到convertView的时候,每次都会根据这个布局去findViewById。如下,使我们通常的写法:
findViewById是在解析layout.xml布局那种其中的子View,解析xml是一个力气活,所以Google也建议我们将这个费力不讨好的活优化起来,所以提出了ViewHolder的概念。
即,使用一个静态类,保存xml中的各个子View的引用关系,这样就不必要每次都去解析xml了。如下:就是针对上面代码写的一个ViewHolder
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_view, null);
}
TextView titleTextView = (TextView) convertView.findViewById(R.id.text));
ImageView iconImageView = (ImageView)convertView.findViewButId( R.id.icon));
//DoSomething…
findViewById是在解析layout.xml布局那种其中的子View,解析xml是一个力气活,所以Google也建议我们将这个费力不讨好的活优化起来,所以提出了ViewHolder的概念。
即,使用一个静态类,保存xml中的各个子View的引用关系,这样就不必要每次都去解析xml了。如下:就是针对上面代码写的一个ViewHolder
static class ViewHolder {
TextView titleTextView;
ImageView iconImageView;
}
但是,在getView方法中我们只能拿到三个参数,position、convertView、viewGroup是拿不到我们自定义的ViewHolder的。所以,我们希望通过convertView拿到ViewHolder只能将其放在tag里。
下面是一个完整的ViewHolder使用exmaple:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_view, null);
holder = new ViewHolder();
holder.titleTextView = (TextView) convertView.findViewById(R.id.text);
holder.iconImageView = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.titleTextView.setText(DATA[pos].title);
holder.iconImageView.setImageBitmap(DATA[pos].bitmap);
return convertView;
}
static class ViewHolder {
TextView titleTextView;
ImageView iconImageView;
}
Tips. Support.v7中的RecyclerView 就是采用了此思想来制作的。
多个类型的ViewType
当我们在Adapter中调用方法getView的时候,如果整个列表中的Item View如果有多种类型布局,如:
我们继续使用convertView来将数据从新填充貌似不可行了,因为每次返回的convertView类型都不一样,无法重用。
Android在设计上的时候,也想到了这点。所以,在adapter中预留的两个方法。
public int getItemViewType(int position) ;
public int getViewTypeCount();
只需要重新这两个方法,设置一下ItemViewType的个数和判断方法,Recycler就能有选择性的给出不同的convertView了。
Example:
@Override
public intgetItemViewType(int position) {
if (DATA[pos].type == ) {
return ;
} else {
return 1;
}
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View convertView, ViewGroup arg2) {
TitleViewHolder titleHolder;
InfoViewHolder infoHolder;
int type = getItemViewType(position);
if (convertView == null) {
switch (type) {
case :
convertView = mInflater.inflate(R.layout.item_view, null);
titleHolder = new TitleViewHolder();
titleHolder.titleTextView = (TextView) convertView.findViewById(R.id.text);
titleHolder.iconImageView = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(titleHolder);
break;
case 1:
convertView = mInflater.inflate(R.layout.item_view2, null);
infoHolder = new InfoViewHolder();
infoHolder.titleTextView = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(infoHolder);
break;
}
} else {
switch (type) {
case :
titleHolder = (TitleViewHolder) convertView.getTag();
break;
case 1:
infoHolder = (InfoViewHolder) convertView.getTag();
break;
}
}
switch (type) {
case :
titleHolder.titleTextView.setText(DATA[pos].title);
break;
case 1:
infoHolder.titleTextView.setText(DATA[pos].title);
infoHolder.iconImageView.setImageBitmap(DATA[pos].bitmap);
break;
}
return convertView;
}
static class TitleViewHolder {
public ImageView iconImageView;
public TextView titleTextView;
}
static class InfoViewHolder {
TextView titleTextView;
ImageView iconImageView;
}
NotifyDataSetChanged刷新机制
当ListView中的数据发生了改变,我们希望刷新ListView中的View时,我们一般会调用NotifyDataSetChanged来刷新ListView。看一下它的源码:
public void notifyChanged() {
synchronized (mObservers) {
// 向每一个子View发送onChanged
mObservers.get(i).onChanged();
}
}
}
发 现它针对每一个子View都做了刷新,当然,如果我们的数据都变量还可以理解。但是,一般条件下,我们需要更新的View不多。频繁的调用 NotifyDataSetChanged方法,刷新整个界面不合适。这样会把界面上显示的所有item都全部重绘一次,即使只有一个view的内容发生 了变化。
所以,我们可以写一个update的方法,来单独刷新一个View
private void updateView(int itemIndex){
intvisiblePosition = yourListView.getFirstVisiblePosition();
ViewHolder viewHolder =(ViewHolder)v.getTag();
if(viewHolder!= null){
viewHolder.titleTextView.setText(“我更新了”);
}
}
Adapter中的网络图片优化
ListView中的每一项Item基本都会带着网络图片,当item比较多的时候,过多的网络请求和过多的图片存储都会是ListView变慢变卡。
所以针对其做一下优化:
● 采用线程池进行网络图片请求,网络图片请求获取后使用本地缓存处理(LRUCache),内存+本地文件缓存。当然,为了防止内存溢出与回收不及时,需要使用弱引用(WeakReference)来存储内存中的图片。
● 对网络中取到的图片进行按比例缩放,以减少内存消耗。
● 滑动的时候不需要对网络图片进行请求。因为,网络请求一般比较耗时,某Item的图片,在请求来的时候如果被Recycler换掉,图片就会对应不上该Item。
Tips.网络请求的工具类比较多不方便举例子,但是使用比较频繁的网络图片请求工具类就是Volley了,Volley提供了一个ImageLoader的工具类和NetworkImageView的网络图片请求View
本文链接:http://www.eoeandroid.com/thread-536377-1-1.html
Android应用之利用getItemViewType为Listview的item设置不同的布局
一、概述
在项目的需求中,有一处需要显示一个交易记录的列表,这个列表很容易让人联想到用listview来实现,但是这个列表又有稍许不同的地方,那就是它里面的item并不是一样的布局,其中某些部分显示的是消费的记录,而有些地方显示的是充值的记录,也就对应了不同的item布局。而且,这两处地方都是从服务端获取数据的,这两个item的数据对应的类内容也各不相同,该怎么处理呢?
下面来一步步实现这个效果。
二、先看效果图

三、实现步骤
实现的原理就是listview的adapter中的一个关键的方法就是getItemViewType(getItemViewType),这个方法有一个参数是position,有了这个position我们就可以对list集合中的不同位置的数据进行不同的处理,进而标识不同的type,将list中的数据进行分类处理。
首先进行,数据的准备:
在这个项目中,数据源是从服务端获取的json数据,数据的格式如下:
<div class="line alt2">
`02.`<span class="content"><span class="block">`"status_code"``: ``"0"``,`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`"result"``: [`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`{`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block">`"mr_content"``: {`</span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block">`"point"``: ``"10"``,`</span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`"member_money"``: ``"100"``,`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block">`"pay_money"``: ``"300"``,`</span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`"cash"``: ``"200"``,`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`"bonus"``: ``"消费满200元立减50元餐券1张"``,`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`"activities"``: ``"三锅鸡1元任吃"``,`</span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block">`"coupon"``: ``"满100送50"``,`</span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`"branch_name"``: ``"四海一家"`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`},`</span></span>
</div>
<div class="line alt1">
`15.`<span class="content"><span class="block">`"mr_id"``: ``"25"``,`</span></span>
</div>
<div class="line alt2">
`16.`<span class="content"><span class="block">`"mr_createtime"``: ``"1333333333"``,`</span></span>
</div>
<div class="line alt1">
`17.`<span class="content"><span class="block">`"mr_type"``: ``"0"``,`</span></span>
</div>
<div class="line alt2">
`18.`<span class="content"><span class="block">`"user_id"``: ``"108"``,`</span></span>
</div>
<div class="line alt1">
`19.`<span class="content"><span class="block">`"merchant_id"``: ``"1"``,`</span></span>
</div>
<div class="line alt2">
`20.`<span class="content"><span class="block">`"branch_id"``: ``"1"``,`</span></span>
</div>
<div class="line alt1">
`21.`<span class="content"><span class="block">`"branch_name"``: ``"ffff"`</span></span>
</div>
<div class="line alt2">
`22.`<span class="content"><span class="block">`},`</span></span>
</div>
<div class="line alt1">
`23.`<span class="content"><span class="block">`{`</span></span>
</div>
<div class="line alt2">
`24.`<span class="content"><span class="block">`"mr_content"``: {`</span></span>
</div>
<div class="line alt1">
`25.`<span class="content"><span class="block">`"member_money"``: ``"300"``,`</span></span>
</div>
<div class="line alt2">
`26.`<span class="content"><span class="block">`"branch_name"``: ``"四海一家"`</span></span>
</div>
<div class="line alt1">
`27.`<span class="content"><span class="block">`},`</span></span>
</div>
<div class="line alt2">
`28.`<span class="content"><span class="block">`"mr_id"``: ``"30"``,`</span></span>
</div>
<div class="line alt1">
`29.`<span class="content"><span class="block">`"mr_createtime"``: ``"1333333333"``,`</span></span>
</div>
<div class="line alt2">
`30.`<span class="content"><span class="block">`"mr_type"``: ``"1"``,`</span></span>
</div>
<div class="line alt1">
`31.`<span class="content"><span class="block">`"user_id"``: ``"108"``,`</span></span>
</div>
<div class="line alt2">
`32.`<span class="content"><span class="block">`"merchant_id"``: ``"1"``,`</span></span>
</div>
<div class="line alt1">
`33.`<span class="content"><span class="block">`"branch_id"``: ``"1"``,`</span></span>
</div>
<div class="line alt2">
`34.`<span class="content"><span class="block">`"branch_name"``: ``"fff"`</span></span>
</div>
<div class="line alt1">
`35.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`36.`<span class="content"><span class="block">`],`</span></span>
</div>
<div class="line alt1">
`37.`<span class="content"><span class="block">`"status_desc"``: ``"ok"`</span></span>
</div>
<div class="line alt2">
`38.`<span class="content"><span class="block">`}`</span></span>
</div>
可以看到其中mr_content这个字段,是一个自定义对象,但是两个mr_content的内容不同,这里是分别为mr_content的内容定义两个不同的类还是如何处理呢?
一开始,我是分别为两个mr_content定义不同的类,后来发现这样行不通,因为这样做的话定义外层类的时候mr_content就无法指定数据类型了。所以,最后采用某人的方法将mr_content定义为一个类,将两个不同的mr_content的字段都定义进去,解析的时候不会出现问题,没有数据会显示null
下面是我定义的mr_content字段的数据类型ComsumAndChargeRecordBean
<div class="line alt2">
`02.`<span class="content"><span class="block">`private` `String branch_name;`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`private` `String pay_money;`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`private` `String coupon;``//使用特权`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block">`private` `String activities;`</span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block">`private` `String member_money;`</span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`private` `String cash;`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block">`private` `String point;`</span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`private` `String bonus;`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`// private String prestore_money;//预存款`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block">`public` `String getBranch_name() {`</span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`return` `branch_name;`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`15.`<span class="content"><span class="block">`public` `void` `setBranch_name(String branch_name) {`</span></span>
</div>
<div class="line alt2">
`16.`<span class="content"><span class="block">`this``.branch_name = branch_name;`</span></span>
</div>
<div class="line alt1">
`17.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`18.`<span class="content"><span class="block">`public` `String getPay_money() {`</span></span>
</div>
<div class="line alt1">
`19.`<span class="content"><span class="block">`return` `pay_money;`</span></span>
</div>
<div class="line alt2">
`20.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`21.`<span class="content"><span class="block">`public` `void` `setPay_money(String pay_money) {`</span></span>
</div>
<div class="line alt2">
`22.`<span class="content"><span class="block">`this``.pay_money = pay_money;`</span></span>
</div>
<div class="line alt1">
`23.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`24.`<span class="content"><span class="block">`public` `String getCoupon() {`</span></span>
</div>
<div class="line alt1">
`25.`<span class="content"><span class="block">`return` `coupon;`</span></span>
</div>
<div class="line alt2">
`26.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`27.`<span class="content"><span class="block">`public` `void` `setCoupon(String coupon) {`</span></span>
</div>
<div class="line alt2">
`28.`<span class="content"><span class="block">`this``.coupon = coupon;`</span></span>
</div>
<div class="line alt1">
`29.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`30.`<span class="content"><span class="block">`public` `String getActivities() {`</span></span>
</div>
<div class="line alt1">
`31.`<span class="content"><span class="block">`return` `activities;`</span></span>
</div>
<div class="line alt2">
`32.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`33.`<span class="content"><span class="block">`public` `void` `setActivities(String activities) {`</span></span>
</div>
<div class="line alt2">
`34.`<span class="content"><span class="block">`this``.activities = activities;`</span></span>
</div>
<div class="line alt1">
`35.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`36.`<span class="content"><span class="block">`public` `String getMember_money() {`</span></span>
</div>
<div class="line alt1">
`37.`<span class="content"><span class="block">`return` `member_money;`</span></span>
</div>
<div class="line alt2">
`38.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`39.`<span class="content"><span class="block">`public` `void` `setMember_money(String member_money) {`</span></span>
</div>
<div class="line alt2">
`40.`<span class="content"><span class="block">`this``.member_money = member_money;`</span></span>
</div>
<div class="line alt1">
`41.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`42.`<span class="content"><span class="block">`public` `String getCash() {`</span></span>
</div>
<div class="line alt1">
`43.`<span class="content"><span class="block">`return` `cash;`</span></span>
</div>
<div class="line alt2">
`44.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`45.`<span class="content"><span class="block">`public` `void` `setCash(String cash) {`</span></span>
</div>
<div class="line alt2">
`46.`<span class="content"><span class="block">`this``.cash = cash;`</span></span>
</div>
<div class="line alt1">
`47.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`48.`<span class="content"><span class="block">`public` `String getPoint() {`</span></span>
</div>
<div class="line alt1">
`49.`<span class="content"><span class="block">`return` `point;`</span></span>
</div>
<div class="line alt2">
`50.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`51.`<span class="content"><span class="block">`public` `void` `setPoint(String point) {`</span></span>
</div>
<div class="line alt2">
`52.`<span class="content"><span class="block">`this``.point = point;`</span></span>
</div>
<div class="line alt1">
`53.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`54.`<span class="content"><span class="block">`public` `String getBonus() {`</span></span>
</div>
<div class="line alt1">
`55.`<span class="content"><span class="block">`return` `bonus;`</span></span>
</div>
<div class="line alt2">
`56.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`57.`<span class="content"><span class="block">`public` `void` `setBonus(String bonus) {`</span></span>
</div>
<div class="line alt2">
`58.`<span class="content"><span class="block">`this``.bonus = bonus;`</span></span>
</div>
<div class="line alt1">
`59.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`60.`<span class="content"><span class="block">`}`</span></span>
</div>
数据准备好了,下面是传入listview中进行显示:
布局文件:
<div class="line alt2">
`02.`<span class="content"><span class="block">`<LinearLayout xmlns:android=``"<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`android:layout_width=``"match_parent"`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`android:layout_height=``"match_parent"`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block">`android:orientation=``"vertical"` `>`</span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`<include`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block">`android:id=``"@+id/traderecord_layout"`</span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`layout=``"@layout/topview_activity"` `/>`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`<ListView`</span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block">`android:id=``"@+id/lv_my_traderecord"`</span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`android:layout_width=``"match_parent"`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`android:layout_height=``"match_parent"` `>`</span></span>
</div>
<div class="line alt1">
`15.`<span class="content"><span class="block">`</ListView>`</span></span>
</div>
<div class="line alt2">
`16.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`17.`<span class="content"><span class="block">`</LinearLayout>`</span></span>
</div>
两个不同item的布局文件就省略了,相信大家都会,这个没什么难度
下面是主界面代码:
<div class="line alt2">
`02.`<span class="content"><span class="block">`// TODO Auto-generated method stub`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`super``.onCreate(savedInstanceState);`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`setContentView(R.layout.activity_trade_record);`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block">`mListView = (ListView) findViewById(R.id.lv_my_traderecord);`</span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`E_TempTradeRecordAdapter adapter = ``new` `E_TempTradeRecordAdapter(`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block">`E_TradeRecordActivity.``this``, myModel.tradeRecordList);`</span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`mListView.setAdapter(adapter);`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`adapter.notifyDataSetChanged();`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`}`</span></span>
</div>
下面是adapter适配器的一部分代码:
字段和构造函数:
<div class="line alt2">
`02.`<span class="content"><span class="block">`private` `static` `final` `int` `TYPE_COUNT = ``2``;``//item类型的总数`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`private` `static` `final` `int` `TYPE_COMSUM = ````;``//消费类型`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`private` `static` `final` `int` `TYPE_CHARGE = ``1``;``//充值类型`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block">`private` `ArrayList<TradeRecordBean> dataList = ``new` `ArrayList<TradeRecordBean>();``//数据集合`</span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block">`private` `Context mContext;`</span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`private` `int` `currentType;``//当前item类型`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`public` `E_TempTradeRecordAdapter(Context mContext,`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`ArrayList<TradeRecordBean> dataList) {`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`super``();`</span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block">`this``.dataList = dataList;`</span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`this``.mContext = mContext;`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`}`</span></span>
</div>
几个重要方法:
<div class="line alt2">
`02.`<span class="content"><span class="block">`public` `int` `getCount() {`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`// TODO Auto-generated method stub`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`return` `dataList.size();`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`@Override`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block">`public` `Object getItem(``int` `position) {`</span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`// TODO Auto-generated method stub`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`return` `dataList.get(position);`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`@Override`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`public` `long` `getItemId(``int` `position) {`</span></span>
</div>
<div class="line alt1">
`15.`<span class="content"><span class="block">`// TODO Auto-generated method stub`</span></span>
</div>
<div class="line alt2">
`16.`<span class="content"><span class="block">`return` `position;`</span></span>
</div>
<div class="line alt1">
`17.`<span class="content"><span class="block">`}`</span></span>
</div>
获取子item的类型 获取类型的数量 这里是根据字段Mr_type来确定的,json数据里面是根据这个字段来确定消费记录的类型的。总之,在为item设置不同的布局的时候肯定有一个标记用来区分不同的item,你可以用这个作为判断的标记,来设置不同的type。
<div class="line alt2">
`02.`<span class="content"><span class="block">`public` `int` `getItemViewType(``int` `position) {`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`// TODO Auto-generated method stub`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`if` `(``"0"``.equals(dataList.get(position).getMr_type())) {`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block">`return` `TYPE_COMSUM;``// 消费类型`</span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block">`} ``else` `if` `(``"1"``.equals(dataList.get(position).getMr_type())) {`</span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`return` `TYPE_CHARGE;``// 充值类型`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block">`} ``else` `{`</span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`return` `100``;`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`@Override`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`public` `int` `getViewTypeCount() {`</span></span>
</div>
<div class="line alt1">
`15.`<span class="content"><span class="block">`return` `TYPE_COUNT;`</span></span>
</div>
<div class="line alt2">
`16.`<span class="content"><span class="block">`}`</span></span>
</div>
viewholder:缓存这几个textview控件
<div class="line alt2">
`02.`<span class="content"><span class="block">`* 消费记录`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`* @author yl`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`*`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block">`*/`</span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block">`class` `ComsumViewHolder {`</span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`TextView branchnameCom;`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block">`TextView comsumemoney;`</span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`TextView useprevillage;`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`TextView yuezhifu;`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`TextView cash;`</span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block">`TextView thisscore;`</span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`TextView extrareward;`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`TextView prestoremoney;`</span></span>
</div>
<div class="line alt1">
`15.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`16.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`17.`<span class="content"><span class="block">`/**`</span></span>
</div>
<div class="line alt2">
`18.`<span class="content"><span class="block">`* 充值记录`</span></span>
</div>
<div class="line alt1">
`19.`<span class="content"><span class="block">`* @author yl`</span></span>
</div>
<div class="line alt2">
`20.`<span class="content"><span class="block">`*`</span></span>
</div>
<div class="line alt1">
`21.`<span class="content"><span class="block">`*/`</span></span>
</div>
<div class="line alt2">
`22.`<span class="content"><span class="block">`class` `ChargeViewHolder {`</span></span>
</div>
<div class="line alt1">
`23.`<span class="content"><span class="block">`TextView branchnameCha;`</span></span>
</div>
<div class="line alt2">
`24.`<span class="content"><span class="block">`TextView prestoremoney;`</span></span>
</div>
<div class="line alt1">
`25.`<span class="content"><span class="block">`TextView extrasmoney;`</span></span>
</div>
<div class="line alt2">
`26.`<span class="content"><span class="block">`TextView totalmoney;`</span></span>
</div>
<div class="line alt1">
`27.`<span class="content"><span class="block">`}`</span></span>
</div>
最后是getview方法:其中有一个关键的方法
这个方法获取到当前position的类型,也就是在前面的getItemViewType方法设置的类型。
其中对convertView进行了复用和holder的使用,算是对listview的优化吧。
当currentType == TYPE_COMSUM,消费类型时,加载comsumView = LayoutInflater.from(mContext).inflate( R.layout.traderecord_item_comsume, null);消费类型的布局文件。反之,加载充值类型的布局文件。这样就可以达到为不同的item设置不同的布局文件了。
<div class="line alt2">
`02.`<span class="content"><span class="block">`// TODO Auto-generated method stub`</span></span>
</div>
<div class="line alt1">
`03.`<span class="content"><span class="block">`View comsumView = ``null``;`</span></span>
</div>
<div class="line alt2">
`04.`<span class="content"><span class="block">`View chargeView = ``null``;`</span></span>
</div>
<div class="line alt1">
`05.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt2">
`06.`<span class="content"><span class="block">`ComsumAndChargeRecordBean record = (ComsumAndChargeRecordBean) dataList`</span></span>
</div>
<div class="line alt1">
`07.`<span class="content"><span class="block">`.get(position).getMr_content();`</span></span>
</div>
<div class="line alt2">
`08.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`09.`<span class="content"><span class="block">`currentType = getItemViewType(position);`</span></span>
</div>
<div class="line alt2">
`10.`<span class="content"><span class="block">`if` `(currentType == TYPE_COMSUM) {`</span></span>
</div>
<div class="line alt1">
`11.`<span class="content"><span class="block">`ComsumViewHolder comsumHolder = ``null``;`</span></span>
</div>
<div class="line alt2">
`12.`<span class="content"><span class="block">`if` `(convertView == ``null``) {`</span></span>
</div>
<div class="line alt1">
`13.`<span class="content"><span class="block">`comsumHolder = ``new` `ComsumViewHolder();`</span></span>
</div>
<div class="line alt2">
`14.`<span class="content"><span class="block">`comsumView = LayoutInflater.from(mContext).inflate(`</span></span>
</div>
<div class="line alt1">
`15.`<span class="content"><span class="block">`R.layout.traderecord_item_comsume, ``null``);`</span></span>
</div>
<div class="line alt2">
`16.`<span class="content"><span class="block">`comsumHolder.branchnameCom = (TextView) comsumView`</span></span>
</div>
<div class="line alt1">
`17.`<span class="content"><span class="block">`.findViewById(R.id.tv_branch_name);`</span></span>
</div>
<div class="line alt2">
`18.`<span class="content"><span class="block">`comsumHolder.comsumemoney = (TextView) comsumView`</span></span>
</div>
<div class="line alt1">
`19.`<span class="content"><span class="block">`.findViewById(R.id.tv_comsumemoney);`</span></span>
</div>
<div class="line alt2">
`20.`<span class="content"><span class="block">`comsumHolder.useprevillage = (TextView) comsumView`</span></span>
</div>
<div class="line alt1">
`21.`<span class="content"><span class="block">`.findViewById(R.id.tv_useprevillage);`</span></span>
</div>
<div class="line alt2">
`22.`<span class="content"><span class="block">`comsumHolder.yuezhifu = (TextView) comsumView`</span></span>
</div>
<div class="line alt1">
`23.`<span class="content"><span class="block">`.findViewById(R.id.tv_yuezhifu);`</span></span>
</div>
<div class="line alt2">
`24.`<span class="content"><span class="block">`comsumHolder.cash = (TextView) comsumView`</span></span>
</div>
<div class="line alt1">
`25.`<span class="content"><span class="block">`.findViewById(R.id.tv_cash);`</span></span>
</div>
<div class="line alt2">
`26.`<span class="content"><span class="block">`comsumHolder.thisscore = (TextView) comsumView`</span></span>
</div>
<div class="line alt1">
`27.`<span class="content"><span class="block">`.findViewById(R.id.tv_thisscore);`</span></span>
</div>
<div class="line alt2">
`28.`<span class="content"><span class="block">`comsumHolder.extrareward = (TextView) comsumView`</span></span>
</div>
<div class="line alt1">
`29.`<span class="content"><span class="block">`.findViewById(R.id.tv_extrareward);`</span></span>
</div>
<div class="line alt2">
`30.`<span class="content"><span class="block">`comsumView.setTag(comsumHolder);`</span></span>
</div>
<div class="line alt1">
`31.`<span class="content"><span class="block">`convertView = comsumView;`</span></span>
</div>
<div class="line alt2">
`32.`<span class="content"><span class="block">`} ``else` `{`</span></span>
</div>
<div class="line alt1">
`33.`<span class="content"><span class="block">`comsumHolder = (ComsumViewHolder) convertView.getTag();`</span></span>
</div>
<div class="line alt2">
`34.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt1">
`35.`<span class="content"><span class="block">`comsumHolder.branchnameCom.setText(DateFormatUtil.formatDate(Long`</span></span>
</div>
<div class="line alt2">
`36.`<span class="content"><span class="block">`.valueOf(dataList.get(position).getMr_createtime()))`</span></span>
</div>
<div class="line alt1">
`37.`<span class="content"><span class="block">`+ ``" "`</span></span>
</div>
<div class="line alt2">
`38.`<span class="content"><span class="block">`+ record.getBranch_name());``// 消费时间和分店`</span></span>
</div>
<div class="line alt1">
`39.`<span class="content"><span class="block">`comsumHolder.comsumemoney.setText(record.getPay_money());``// 消费金额`</span></span>
</div>
<div class="line alt2">
`40.`<span class="content"><span class="block">`comsumHolder.useprevillage.setText(record.getCoupon());``// 使用特权`</span></span>
</div>
<div class="line alt1">
`41.`<span class="content"><span class="block">`comsumHolder.yuezhifu.setText(record.getMember_money());``// 余额支付`</span></span>
</div>
<div class="line alt2">
`42.`<span class="content"><span class="block">`comsumHolder.cash.setText(record.getCash());``// 现金支付`</span></span>
</div>
<div class="line alt1">
`43.`<span class="content"><span class="block">`comsumHolder.thisscore.setText(record.getPoint());``// 本次积分`</span></span>
</div>
<div class="line alt2">
`44.`<span class="content"><span class="block">`comsumHolder.extrareward.setText(record.getBonus());``// 额外奖励`</span></span>
</div>
<div class="line alt1">
`45.`<span class="content"><span class="block">`} ``else` `if` `(currentType == TYPE_CHARGE) {`</span></span>
</div>
<div class="line alt2">
`46.`<span class="content"><span class="block">`ChargeViewHolder chargeHoler = ``null``;`</span></span>
</div>
<div class="line alt1">
`47.`<span class="content"><span class="block">`if` `(convertView == ``null``) {`</span></span>
</div>
<div class="line alt2">
`48.`<span class="content"><span class="block">`chargeHoler = ``new` `ChargeViewHolder();`</span></span>
</div>
<div class="line alt1">
`49.`<span class="content"><span class="block">`chargeView = LayoutInflater.from(mContext).inflate(`</span></span>
</div>
<div class="line alt2">
`50.`<span class="content"><span class="block">`R.layout.traderecord_item_chongzhi, ``null``);`</span></span>
</div>
<div class="line alt1">
`51.`<span class="content"><span class="block">`chargeHoler.branchnameCha = (TextView) chargeView`</span></span>
</div>
<div class="line alt2">
`52.`<span class="content"><span class="block">`.findViewById(R.id.tv_branchname_charge);`</span></span>
</div>
<div class="line alt1">
`53.`<span class="content"><span class="block">`chargeHoler.prestoremoney = (TextView) chargeView`</span></span>
</div>
<div class="line alt2">
`54.`<span class="content"><span class="block">`.findViewById(R.id.tv_prestoremoney);`</span></span>
</div>
<div class="line alt1">
`55.`<span class="content"><span class="block">`chargeHoler.extrasmoney = (TextView) chargeView`</span></span>
</div>
<div class="line alt2">
`56.`<span class="content"><span class="block">`.findViewById(R.id.tv_extrasmoney);`</span></span>
</div>
<div class="line alt1">
`57.`<span class="content"><span class="block">`chargeHoler.totalmoney = (TextView) chargeView`</span></span>
</div>
<div class="line alt2">
`58.`<span class="content"><span class="block">`.findViewById(R.id.tv_totalmoney);`</span></span>
</div>
<div class="line alt1">
`59.`<span class="content"><span class="block">`chargeView.setTag(chargeHoler);`</span></span>
</div>
<div class="line alt2">
`60.`<span class="content"><span class="block">`convertView = chargeView;`</span></span>
</div>
<div class="line alt1">
`61.`<span class="content"><span class="block">`} ``else` `{`</span></span>
</div>
<div class="line alt2">
`62.`<span class="content"><span class="block">`chargeHoler = (ChargeViewHolder) convertView.getTag();`</span></span>
</div>
<div class="line alt1">
`63.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`64.`<span class="content"><span class="block"> </span></span>
</div>
<div class="line alt1">
`65.`<span class="content"><span class="block">`chargeHoler.branchnameCha.setText(DateFormatUtil.formatDate(Long`</span></span>
</div>
<div class="line alt2">
`66.`<span class="content"><span class="block">`.valueOf(dataList.get(position).getMr_createtime()))`</span></span>
</div>
<div class="line alt1">
`67.`<span class="content"><span class="block">`+ ``" "`</span></span>
</div>
<div class="line alt2">
`68.`<span class="content"><span class="block">`+ record.getBranch_name());``// 消费时间和分店`</span></span>
</div>
<div class="line alt1">
`69.`<span class="content"><span class="block">`// chargeHoler.prestoremoney.setText(record.getPrestore_money() +`</span></span>
</div>
<div class="line alt2">
`70.`<span class="content"><span class="block">`// "元");// 存款`</span></span>
</div>
<div class="line alt1">
`71.`<span class="content"><span class="block">`chargeHoler.extrasmoney.setText(record.getMember_money() + ``"元"``);``// 余额`</span></span>
</div>
<div class="line alt2">
`72.`<span class="content"><span class="block">`chargeHoler.totalmoney.setText(record.getMember_money() + ``"元"``);``// 合计`</span></span>
</div>
<div class="line alt1">
`73.`<span class="content"><span class="block">`}`</span></span>
</div>
<div class="line alt2">
`74.`<span class="content"><span class="block">`return` `convertView;`</span></span>
</div>
<div class="line alt1">
`75.`<span class="content"><span class="block">`}`</span></span>
</div>
上面就是整个效果的实现过程
四、总结
其实为listview的item设置不同的布局文件,达到上面的效果,步骤如下;
1、为不同的item写不同的布局文件,设置统一的javabean类
2、继承BaseAdapter类,实现getItemViewType(int position)和getViewTypeCount() 方法,根据这两个方法,为item设置不同的标记,也就是不同的type
3、在getView方法中,利用getItemViewType(position)方法获取当前的type类型,然后根据不同的type类型,加载不同的item布局文件。
4、其他的一些listview的优化同一般的listview没有很大区别。
转自:http://www.it165.net/pro/html/201406/16181.html
💬 评论