本文介绍了listview的复用机制
listview 的item只会创建一定数量,只会创建的view会复用之前的
测试代码如下
自定义一个adapter
/**
* Created by xuyushi on 15/8/9.
*/
public class MyAdapter extends ArrayAdapter<String > {
private static final String TAG = "MyAdapter";
private int resourceId ;
public MyAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
this.resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder myViews;
String string = getItem(position);
if (convertView == null) {
Log.d(TAG, "为空:" + position);
myViews = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(resourceId, null);
myViews.mNameText = (TextView) convertView.findViewById(R.id.list_item);
convertView.setTag(myViews);
} else {
myViews = (ViewHolder) convertView.getTag();
Log.d(TAG, "不为空:" + position);
}
myViews.mNameText.setText(string);
return convertView;
}
static class ViewHolder {
private TextView mNameText;
}
}
可以看到 随着listview 往下滚动,打印的都为”不为空"
那么问题来了
比如异步加载图片,最终造成界面显示的混乱
举个例子:listview中有一个imageview,动态的加载网络图片
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
final String url = getItem(position);
View view;
if (convertView == null)
{
view = LayoutInflater.from(getContext()).inflate(R.layout.photo_layout, null);
} else
{
view = convertView;
}
final ImageView photo = (ImageView) view.findViewById(R.id.photo);
// 给ImageView设置一个Tag,保证异步加载图片时不会乱序
photo.setTag(url);
new LoadImgTask(photo).execute(url);
return view;
}
当第一页的imageview开启异步线程加载图片时候,listview下翻,新的item会复用之前恩item,而且setTag会覆盖之前的tag。当第一屏的ItemView的图片下载完成后,如果直接findViewByTag然后设置图片会显示在第二屏上,就混乱了,所以一般在显示前都会判断photo.getTag().equals(url);确定了再显示。也就是说第一屏的ItemView图片下载完了,但是Tag被覆盖了,所以即使下载完成了,也不会有任何显示。这就解释了为什么我们防止混乱的代码需要那样去写。