前面看到有帖子中有人使用notifyDataSetChanged()来解决ListView中异步加载图片第一张图片显示错误问题。首先在数据源没有变化的情况下没有必要使用notifyDataSetChanged(),会导致调用requestLayout()重绘当前界面的列,就是重新走getView().所以notifyDataSetChanged()在图片都已下载缓存完的情况下正常显示了,但是因为重新刷新界面了导致了效率变低。其实要知道ListView图片混乱都是因为重用了ConvertView,但这个是ListView性能的关键。我们为什么说建议在ListView中使用ViewHolder,按我的理解其一是能够保存ConvertView中各个View的引用,使得不需要每次都findViewById严重影响效率,其二是我们可以拿到View的引用后使用setTag()和getTag()方法,道理跟ConvertView.setTag()和ConvertView.getTag()是一样的。所以在异步加载图片的时候我们给予ImageView一个Tag,在加载完成回调的时候根据这个Tag来判断是否要把图片设置到当前的ImageView中。 ? 代码片段,双击复制 01 private final ArrayList<View> mActiveImages = new ArrayList<View>(); ? 代码片段,双击复制 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 @Override public View getView( int position, View convertView, ViewGroup parent) { ViewHolder holder = null ; if (convertView == null ) { // inflate convertView holder = new ViewHolder(); // initial holer,means findViewById convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } // do your stuff // add first then load icon,make sure we have the image holding the icon is contained at mActiveImages mActiveImages.remove(holder.mIcon); mActiveImages.add(holder.mIcon); // set tag to imageview for not messing up the images holder.mIcon.setTag( "your tag" ); // here load Icon return convertView; } 另外要善于利用AbsListView.RecyclerListener接口,使用这个接口可以达到只更新当前界面那些列的图片以及释放其他资源。 ? 代码片段,双击复制 01 02 03 04 05 06 07 08 09 10 11 12 @Override public void onMovedToScrapHeap(View view) { ViewHolder holder = (ViewHolder)view.getTag(); mActiveImages.remove(holder.mIcon); } @Override public void setIcon(ImageView image, String tag, Drawable drawable) { if (mActiveImages.contains(image) && tag.equals(image.getTag())) { image.setImageDrawable(drawable); } } 以上是我的看法,欢迎指正。 本帖地址: http://www.eoeandroid.com/thread-186137-1-1.html [复制链接]