其实还是用convertView/ViewHolder 这种缓存技术比较好,这样子你浏览ListView的时候速度很快。而不采用convertView/ViewHolder 这种缓存技术的时候,你会明显感觉ListView很卡。convertView/ViewHolder 缓存技术的实质,其实就是convertView的复用,因为我在查看convertView是否为null的时候,只有7次它输出null,其余都是convertView不为null。也就是说convertView这个对象引用只有7个(每个手机不同,就是一个屏幕最多容纳的条目数)。convertView/ViewHolder 其实是在复用每一个条目的View。只让这7个引用对应7个View的实例,而不是我们每次都给一个引用建立一个新的View实例。这样子,在ListView绘制调用getView的时候,我们只建立了7个View实例,只是每次把View中的内容改变了一下,比如TextView.setText(str)。这样子程序就很快。
我的adapter编写如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
涉及到加载图片,经常会出现重复。出现重复内容,基本上都是使用了ViewHolder这种方法的。
当我们判断 convertView == null 的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置进去。
如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。
ListView只会缓存第一屏里面的List Item的视图布局,之后滚动ListView后面的Item的布局就都是用前面所缓存的视图布局(也就是convertView不为null)。这样如果当后面的某一条记录里面的某些控件因上面的原因没有赋值,就会直接使用前面所缓存的视图里面的值了(里面有值的话)。
这样的最终效果就是,滚动的时候,会出现前面已经出现过的内容。
解决办法:
如果子控件为ImageView,当赋值内容为空时,直接设定默认的图像资源。如果使用setBackgroundResource可能出现默认的图像资源没有真正的设定到ImageView,必须使用setImageResource。setBackgroundResource是View类中的方法,而setImageResource是ImageView自己的方法。使用前者可能导致图像没有真正的设定到ImageView,此时ImageView显示上一次赋值的图像。
if (holder.iv.getTag() != null
&& !holder.iv.getTag().toString().equals(ConnectNetworkConstant.HOST_URL+model.getPicUrl().toString())) { // 解决图片显示错位
holder.iv.setImageResource(R.drawable.default_image_185_140);
}