关于通过设置imageview的tag避免listview图片错位的疑问

luqing414 2015-11-27 01:43:44
listview图片有可能出现错位,举一个应用场景,界面可以显示7条记录,都是异步从网络加载图片,当第1条记录对应的图片还没显示,而就往下滑动,导致第8条记录出现,而第8条记录的布局重用了第1条记录的,而且第8条对应的图片加载比第1条还快,所以出现了最下面的一条记录先显示第8张图片,再显示第1张图片的情况,出现这种情况的原因是重用了convertView,网上也有解决方案,就是说给imageview设置tag,完后进行比较,但是我看的几个帖子,要么只有文字描述,要么就是代码不全,要么就是东扯西拉没说到重点,具体要怎么比较并不清楚,我写了一个伪代码:


public class MyAdapter extends BaseAdapter {
private List<String> values;
private LayoutInflater mInflater;

public MyAdapter(Context context, List<String> values) {
this.values = values;
mInflater = LayoutInflater.from(context);
}

@Override
public int getCount() {
return values.size();
}

@Override
public Object getItem(int position) {
return values.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
String url = getItem(position).toString();

if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);

holder.image = (ImageView) convertView.findViewById(R.id.pic);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

holder.image.setImageBitmap(BitmapFactory.decodeFile(url));

return convertView;
}

static class ViewHolder {
ImageView image;
}
}


其中假设holder.image.setImageBitmap(BitmapFactory.decodeFile(url));这一句就能异步从网络加载图片(只是假设,实际肯定不行,但这不是我想知道的重点),我想问的是,怎么设置tag并比较可以避免上面那种场景的出现呢,我想过用

if (holder.image.getTag() == url) {
holder.image.setImageBitmap(BitmapFactory.decodeFile(url));
}

holder.image.setTag(url);

或者反之,但仔细一想都不行,请知道的人指点下
...全文
1043 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
luqing414 2015-12-12
  • 打赏
  • 举报
回复
意外在一个讲设计模式的博客中发现了方案 http://blog.csdn.net/bboyfeiyu/article/details/50103471
  • 打赏
  • 举报
回复
引用 15 楼 u013377714 的回复:
[quote=引用 14 楼 luqing414 的回复:] [quote=引用 13 楼 u013377714 的回复:] [quote=引用 11 楼 luqing414 的回复:] [quote=引用 8 楼 u013377714 的回复:] [quote=引用 5 楼 luqing414 的回复:] [quote=引用 2 楼 u013377714 的回复:] 一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
我这本来就是伪代码,我都说了,不要去纠结这个,你就当是加载网络图片,设置默认图片根本不能解决我说的应用场景,设置完后,图片1才加载出来,还是会在图片8处显示图片1[/quote]// 给 ImageView 设置一个 tag holder.img.setTag(imgUrl); // 预设一个图片 holder.img.setImageResource(R.drawable.ic_launcher); // 通过 tag 来防止图片错位 if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) { imageView.setImageBitmap(result); }[/quote] 在哪里setTag,就跟我自己一楼说的那样吗?[/quote]当然是每个都设你放在公共里面就好了。。。他主要是判断你要显示的和tag里面相不相同。。[/quote] 你这样不对,你如果setTag设置在getTag前面,那永远都是equals了[/quote]http://www.360doc.com/content/12/1217/17/7857928_254604452.shtml[/quote] 他这个思路是对的,代码拷过去,改改就能用了 // 通过 tag 来防止图片错位 if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) { imageView.setImageBitmap(result); // 给 ImageView 设置一个 tag holder.img.setTag(result); }else {// 预设一个图片 holder.img.setImageResource(R.drawable.ic_launcher); }
柒加伊 2015-12-04
  • 打赏
  • 举报
回复
这个需要在网络图片下载控件里面判断当前imagView的tag是否是下载图片的Uri, 如果是就设置成下载的图片, 如果不是就设置默认图片.
luqing414 2015-11-30
  • 打赏
  • 举报
回复
引用 13 楼 u013377714 的回复:
[quote=引用 11 楼 luqing414 的回复:] [quote=引用 8 楼 u013377714 的回复:] [quote=引用 5 楼 luqing414 的回复:] [quote=引用 2 楼 u013377714 的回复:] 一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
我这本来就是伪代码,我都说了,不要去纠结这个,你就当是加载网络图片,设置默认图片根本不能解决我说的应用场景,设置完后,图片1才加载出来,还是会在图片8处显示图片1[/quote]// 给 ImageView 设置一个 tag holder.img.setTag(imgUrl); // 预设一个图片 holder.img.setImageResource(R.drawable.ic_launcher); // 通过 tag 来防止图片错位 if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) { imageView.setImageBitmap(result); }[/quote] 在哪里setTag,就跟我自己一楼说的那样吗?[/quote]当然是每个都设你放在公共里面就好了。。。他主要是判断你要显示的和tag里面相不相同。。[/quote] 你这样不对,你如果setTag设置在getTag前面,那永远都是equals了
水的川 2015-11-30
  • 打赏
  • 举报
回复
引用 14 楼 luqing414 的回复:
[quote=引用 13 楼 u013377714 的回复:] [quote=引用 11 楼 luqing414 的回复:] [quote=引用 8 楼 u013377714 的回复:] [quote=引用 5 楼 luqing414 的回复:] [quote=引用 2 楼 u013377714 的回复:] 一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
我这本来就是伪代码,我都说了,不要去纠结这个,你就当是加载网络图片,设置默认图片根本不能解决我说的应用场景,设置完后,图片1才加载出来,还是会在图片8处显示图片1[/quote]// 给 ImageView 设置一个 tag holder.img.setTag(imgUrl); // 预设一个图片 holder.img.setImageResource(R.drawable.ic_launcher); // 通过 tag 来防止图片错位 if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) { imageView.setImageBitmap(result); }[/quote] 在哪里setTag,就跟我自己一楼说的那样吗?[/quote]当然是每个都设你放在公共里面就好了。。。他主要是判断你要显示的和tag里面相不相同。。[/quote] 你这样不对,你如果setTag设置在getTag前面,那永远都是equals了[/quote]http://www.360doc.com/content/12/1217/17/7857928_254604452.shtml
tcmakebest 2015-11-28
  • 打赏
  • 举报
回复
表面上看是设置个 tag, 实质上就是判断下 tag 后不要重用,直接不重用就好了.
luqing414 2015-11-28
  • 打赏
  • 举报
回复
引用 7 楼 u010911576 的回复:
你知道你错在哪吗? 最后return viewHolder.image 而不是convertView
这跟这有什么关系?如果contentView里面不止ImageView一个控件呢
水的川 2015-11-28
  • 打赏
  • 举报
回复
引用 11 楼 luqing414 的回复:
[quote=引用 8 楼 u013377714 的回复:] [quote=引用 5 楼 luqing414 的回复:] [quote=引用 2 楼 u013377714 的回复:] 一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
我这本来就是伪代码,我都说了,不要去纠结这个,你就当是加载网络图片,设置默认图片根本不能解决我说的应用场景,设置完后,图片1才加载出来,还是会在图片8处显示图片1[/quote]// 给 ImageView 设置一个 tag holder.img.setTag(imgUrl); // 预设一个图片 holder.img.setImageResource(R.drawable.ic_launcher); // 通过 tag 来防止图片错位 if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) { imageView.setImageBitmap(result); }[/quote] 在哪里setTag,就跟我自己一楼说的那样吗?[/quote]当然是每个都设你放在公共里面就好了。。。他主要是判断你要显示的和tag里面相不相同。。
luqing414 2015-11-28
  • 打赏
  • 举报
回复
引用 10 楼 tcmakebest 的回复:
表面上看是设置个 tag, 实质上就是判断下 tag 后不要重用,直接不重用就好了.
是不是我一楼说的那样判断?
luqing414 2015-11-28
  • 打赏
  • 举报
回复
引用 8 楼 u013377714 的回复:
[quote=引用 5 楼 luqing414 的回复:] [quote=引用 2 楼 u013377714 的回复:] 一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
我这本来就是伪代码,我都说了,不要去纠结这个,你就当是加载网络图片,设置默认图片根本不能解决我说的应用场景,设置完后,图片1才加载出来,还是会在图片8处显示图片1[/quote]// 给 ImageView 设置一个 tag holder.img.setTag(imgUrl); // 预设一个图片 holder.img.setImageResource(R.drawable.ic_launcher); // 通过 tag 来防止图片错位 if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) { imageView.setImageBitmap(result); }[/quote] 在哪里setTag,就跟我自己一楼说的那样吗?
水的川 2015-11-27
  • 打赏
  • 举报
回复
引用 5 楼 luqing414 的回复:
[quote=引用 2 楼 u013377714 的回复:] 一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
我这本来就是伪代码,我都说了,不要去纠结这个,你就当是加载网络图片,设置默认图片根本不能解决我说的应用场景,设置完后,图片1才加载出来,还是会在图片8处显示图片1[/quote]// 给 ImageView 设置一个 tag holder.img.setTag(imgUrl); // 预设一个图片 holder.img.setImageResource(R.drawable.ic_launcher); // 通过 tag 来防止图片错位 if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) { imageView.setImageBitmap(result); }
_deadline 2015-11-27
  • 打赏
  • 举报
回复
你知道你错在哪吗? 最后return viewHolder.image 而不是convertView
luqing414 2015-11-27
  • 打赏
  • 举报
回复
引用 3 楼 u012092951 的回复:
[quote=引用 2 楼 u013377714 的回复:] 一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
默认图片比较靠谱,建议使用Volley框架。[/quote] Volley框架我看过源码,没看到有针对这方面的优化
luqing414 2015-11-27
  • 打赏
  • 举报
回复
引用 2 楼 u013377714 的回复:
一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
我这本来就是伪代码,我都说了,不要去纠结这个,你就当是加载网络图片,设置默认图片根本不能解决我说的应用场景,设置完后,图片1才加载出来,还是会在图片8处显示图片1
luqing414 2015-11-27
  • 打赏
  • 举报
回复
引用 2 楼 u013377714 的回复:
一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
大哥,都说了是伪代码了
倔强的包子 2015-11-27
  • 打赏
  • 举报
回复
引用 2 楼 u013377714 的回复:
一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
默认图片比较靠谱,建议使用Volley框架。
水的川 2015-11-27
  • 打赏
  • 举报
回复
一看这个判断就有问题,holder.image.getTag() .equals(url)字符串要用equals,另外你这不是从本地文件下加载图片吗?又不是从网络中加载。。最后针对错乱问题,一般都是先设置默认图片,等加载出来再把图片设置进去。。
luqing414 2015-11-27
  • 打赏
  • 举报
回复
我自己想了下,这样写,判断Null是因为第一次没有tag,大家看对不对

if (holder.image.getTag() == null || holder.image.getTag() == url) {
			holder.image.setImageBitmap(BitmapFactory.decodeFile(url));
			holder.image.setTag(url);
		}
ListView异步加载图片图片错位问题解决方案 * 问题分析:我们在使用AsyncTask异步下载图片的时候,经常会用到convertView的重用,一般情况下,滑动后第一个可见的元素(我们给它命个名,称为A1)和 * listview的第一个元素(A)是公用一个convertView的(一般情况),此时问题就来了,如果异步下载图片执行的比较慢,第一个元素对应的url * 下载的图片会放到第一个元素上面还是滑动后第一个可见的元素上面呢? * 解决方案:给每个listviewImageView设置tag,使用findViewWithTag()的方式来得到ImageView,此时图片就不会产生错位了。而且 * 值得注意的是,由于A和A1使用同一个convertView,因此如果A中的ImageView已经有值得话,当A2展示的并且它所对应的图片还未加载完成的时候, * A2会显示A上的图片,这明显是不对的,因此我们这里给它设置一个默认的icon,即mHolder.mImageView.setImageResource(R.drawable.ic_launcher); * 思路简介:一般listview中涉及到图片加载的,为了提高用户体验,一般会使用一个软引用和存文件的方式来实现。不过还见过这样来实现的:即用一个HashMap来存放很小一部分的数据, * 当HashMap中的大小达到一定的值时,清空HashMap,并且将数据放入软应用中。 * 注意操作sdcard权限已经网络访问权限的加入

80,337

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧