工作原理:
- 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进行输出
public class MultipleItemsListextendsListActivity{
private MyCustomAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mAdapter=newMyCustomAdapter();
for (inti=0;i<50;i++)
mAdapter.addItem("item"+i);
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter{
privateArrayList mData=newArrayList();
privateLayoutInflater mInflater;
public MyCustomAdapter(){
mInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(finalString item){
mData.add(item);
notifyDataSetChanged();
}
@Override
public intgetCount(){
return mData.size();
}
@Override
public String getItem(intposition){
return mData.get(position);
}
@Override
public longgetItemId(intposition){
return position;
}
@Override
public View getView(intposition,View convertView,ViewGroup parent){
System.out.println("getView"+position+""+convertView);
ViewHolder holder=null;
if (convertView==null){
convertView=mInflater.inflate(R.layout.item1,null);
holder=newViewHolder();
holder.textView=(TextView)convertView.findViewById(R.id.text);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
执行程序,然后在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的边缘仍然可见,在顶端)
02
-
05
13
:
48
:
25.169
:INFO/System.out(
947
):getView
9
null
|
再滚动List
convertView不是空值了!item1离开屏幕到Recycler中去了,然后item11被创建
02
-
05
13
:
48
:
42.879
:INFO/System.out(
947
):getView
10
android.widget.LinearLayout
@437430f8
|
再滚动:
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
|
convertView 如我们所期待的非空了,在item11离开屏幕之后,它的视图(@437430f8)作为convertView容纳item21了