就发生了,Recycler构件只会缓存一个item,这时毫无争议会缓存Item2,那么item1就被复用,显示为
item8(实际上当item1完全滑出界面时就会被显示作Item8了)。
二,需要注意的地方
1,数据与显示分离
由于ListView的item view是复用的,这就要求我们将数据与显示分离,否则将造成显示的结果错
乱。比如,当ListView的Item中含有单选按钮时,假如只是简单地记录按钮的点击状态,那么当滑动
ListView的时候,“已点击”与“未点击”就显示混乱。再举个例子,ListView的item中含有图片,选择异步
加载。如果做法是当下载完毕后就设置ImageView的显示内容,那么也会造成混乱。
比较明智的做法是自己单独维护一个数据结构来缓存数据,上文的点击状态就时候使用ArrayList,异
步加载的图片就适合使用HashMap。
2,数据更新
ListView的数据更新只能在UI主线程中进行,否则会报:“java.lang.IllegalStateException: The
content of the adapter has changed but ListView did not receive a notification. Make sure the
content of your adapter is not modified from a background thread, but only from the UI thread.”
另外还需要注意的是,不能更改原来的数据指向的对象。比如,原来的数据List 指向的是
ArrayList1。在数据更新后,为了方便,我们直接 List = ArrayList2。这样就使List指向新的ArrayList
,也是会出错的。总而言之,唯一的做法就是在原理的ArrayList1中增加或删除数据。
3,使用BitMap需要注意不要OOM
使用ListView的场景里一般含有多条数据,每条数据都有BitMap的情况下很容易造成OOM。比较合
理的做法是,Bitmap要及时回收,同时,要合理地压缩Bitmap。
三,ListView的优化
1,判断item的view是否为空
如果view为空,就不需要去将XML布局文件转化为View,也就是达到使用recycler缓存的目的。
2,使用ViewHolder
在Android中,一个界面可以被组织为一棵控件树,View的绘制就是围绕这棵控件树来执行的。而
view.findViewById(int id)函数的原理是,从该View开始(包含该view)进行树的深度优先遍历,匹配最
先找到的id为参数id的view(因此android中的id不要求全局唯一,只要能保证准确获取就行)。因此
看来,findViewById这个函数是十分耗时的。因此使用一个内部类ViewHolder可以缓存住item的子控
件,使其只需要进行N次遍历(N = item中控件数 * 一屏能显示的item个数)。
以下是例子:
01 public class MBaseAdapter extends BaseAdapter{
02
03 List mList;
04
05 Context mContext;
06
07 ViewHolder mViewHolder;
08
09
10
11 public MBaseAdapter(Context context,List list) {
12
13 mContext = context;
14
15 mList = list;
16
17 }
18
19
20
21 @Override
22
23 public int getCount() {
24
25 return mList.size();
26
27 }
28
29
30
31 @Override
32
33 public Object getItem(int position) {
34
35 return mList.get(position);
36
37 }
38
39
40
41 @Override
42
43 public long getItemId(int position) {
44
45 return position;
46
47 }
48
49
50
51 @Override
52
53 public View getView(int position, View convertView, ViewGroup arg2) {
54
55 if (convertView == null) {
56
57 convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, null);
58
59 mViewHolder = new ViewHolder();
60
61 mViewHolder.tvHello = (TextView) convertView.findViewById(R.id.list_hello);
62
63 convertView.setTag(mViewHolder);
64
65 } else {
66
67 mViewHolder = (ViewHolder)convertView.getTag();
68
69 }
70
71 mViewHolder.tvHello.setText(mList.get(position)+" Hello,World!");
72
73
74
75 return convertView;
76
77 }
78
79
80
81 class ViewHolder {
82
83 TextView tvHello;
84
85 }
86
87
88
89 }
3,在合适的状态显示合适的数据
这里主要是监听滑动状态,当状态为滑动或者惯性滑动时不需要开加载图片,当状态为普通显示时就加载图片。