ListView适配器及缓存机制
来源:互联网 发布:养生壶 知乎 skg和北鼎 编辑:程序博客网 时间:2024/05/24 07:45
它是如何工作的:
- ListView 向适配器说“给我的每个条目一个布局”
- 一个新的布局创建出来并显示出来
下一个问题:当我们有10亿个条目的时候怎么办,难道新创建一个新的布局并显示出来吗?答案肯定是“不”。Android会为你把布局缓存起来。
这一部分在Android中称呼为"Recycle - 回收利用"。以下为它的具体实现过程图。
- 当你有一亿个条目的时候, 只有可看见的View保存在内存中+Recycle过的View
- 当ListView第一次向适配器请求一个VIew的时候,convertView为null,因此需要新建一个convertView.
- 当ListView请求一个条目item1的VIew,并且item1已经超出屏幕之外,并进来一个相同类型的条目从底部进入到屏幕里面,这时convertVIew 不为null,而是等于item1。 你只需要获取新的数据装载到该View里面并返回回去。而不必要重新创建一个新的VIew
下面为简单的代码实现:
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 0; i < 50; i++) {
mAdapter.addItem("item " + i);
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private ArrayList mData = new ArrayList();
private LayoutInflater mInflater;
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("getView " + position + " " + convertView);
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item1, null);
holder = new ViewHolder();
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;
}
}
运行程序并观察发生了什么
getView方法调用了9次。对于可以看见的VIew中,convertView一直为null。
拖动以下,并查看输出的状态。
就像我们所想到的一样,convertView不为null.当item11超出屏幕之后,并进来item21的时候2个convertView为同一个View。
不同的列表条目的View
我们举一个更加复杂点的例子吧,我们加入一个分隔符到ListView中。
你需要做的是:
- 重写getViewTypeCount() ->它返回不同的View的个数
- getItemViewType(int) -> 根据它的位置返回正确的View类型
- Create correct convertView (depending on view item type) in getView
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 1; i < 50; i++) {
mAdapter.addItem("item " + i);
if (i % 4 == 0) {
mAdapter.addSeparatorItem("separator " + i);
}
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList mData = new ArrayList();
private LayoutInflater mInflater;
private TreeSet mSeparatorsSet = new TreeSet();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
@Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
我们运行并查看以下我们写的代码所输出的东西,我们会发现每隔4个条目它会出现一个分隔符。
查看输出Log,没有什么特别的对于不同的类型 convertView都为Null
拖动一下,看看Log中有什么变化
分隔符的convertView为Null,直到第一个分隔符看见为止。当它超出屏幕时,View还会缓存到Recycler中,以使convertView显示出来。
- ListView适配器及缓存机制
- ListView适配器及缓存机制
- Android性能:经典ListView适配器convertView缓存及复用机制
- Android性能:经典ListView适配器convertView缓存及复用机制
- Andndroid:ListView缓存机制及BaseAdapter
- listview的缓存机制
- ListView缓存机制
- ListView缓存机制
- ListView缓存优化机制
- ListView优化及万能适配器
- ListView的适配器及优化
- 适配器及ListView的优化
- android之listView缓存机制
- 探究ListView 的缓存机制
- ListView源码分析缓存机制
- Listview缓存机制分析(四)
- ListView 缓存机制源码浅析
- ListView适配器以及ListItem回收重用机制
- codeblocks工程下关于结构体的一个问题
- 黑马程序员——Java学习笔记 其他对象
- Eclipse - Method NewStringUTF() could not be resolved
- OTL调用存储过程和函数
- onTouch和onTouchEvent的区别
- ListView适配器及缓存机制
- XMPP功能列表
- 最小点覆盖问题详解
- 黑马程序员--java学习笔记第八天
- POJ 1062 昂贵的婚礼(Dijkstra)
- 学历iOS开发纪录(结构体和数组指针)
- [玩玩Objective-C]之动态绑定
- redis主从的配置和使用
- windows下如何远程连接Linux电脑