android 的 adapter 异步加载图片时如何保持顺序不会错乱

2014-12-11 16:32:13 +08:00
 Registering
一般使用holder的方式自定义一个adapter,每个节点如果是有图片,则异步加载。

但是经常发现图片顺序错乱,得上下拉动让它刷新一下才会恢复。

这个问题困扰了几天,没解决,,
6145 次点击
所在节点    程序员
14 条回复
fangzhzh
2014-12-11 16:59:38 +08:00
show me the code.

possible reasons:
1 viewType
2 no else for if
3 refresh mechanism?
Registering
2014-12-11 17:22:20 +08:00
@fangzhzh
1,只有一种类型的item,所有就不用重写viewtype的两个方法了
2,有else for if
3,,,
代码大概结构如下(异步加载图片的方法里用一个回调方法):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
family = listData.get(position);
if (convertView == null) {
holder = new ViewHolder();
convertView = mLayoutInflater.inflate(rsid, parent, false);
holder.familyFace = (ImageView) convertView
.findViewById(R.id.familyCardFace);
holder.familyName = (TextView) convertView
.findViewById(R.id.familyCardName);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.familyName.setText(family.getName());

cache.loadBitmaps(holder.familyFace, family.getPortrait(), null,
new SetImageCallBack() {
@Override
public void setImage(ImageView imageView, Bitmap bitmap) {
// TODO Auto-generated method stub
Bitmap bitmap1 = BitmapUtils.centerSquareScaleBitmap(
bitmap, GRIDSIZE);
imageView.setImageBitmap(bitmap1);
}
});
return convertView;
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return listData.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
Registering
2014-12-11 17:23:10 +08:00
@fangzhzh 没有markdown感觉活不下去了
vileer
2014-12-11 20:04:46 +08:00
cache对应的应该是position而不应该是具体的view(你代码里面的是imageView)
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
family = listData.get(position);
// 省略掉创建holder的过程
holder.familyName.setText(family.getName());

Bitmap bitmap1 = cache.loadBitmaps(position);
if(bitmap1 == null) {
cache.asyncLoadBitmaps(position);
} else {
holder.familyFace.setImageBitmap(bitmap1);
}
return convertView;
}

class Cache {
public void asyncLoadBitmaps(int index){
// 异步加载
// 加载完后发消息给UI线程调用adapter的notifyDataSetChanged();
}
}
fangzhzh
2014-12-11 20:29:04 +08:00
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return listData.get(position);;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return uniqueId???;
}
Registering
2014-12-11 20:40:13 +08:00
@vileer thx,按你的方法搞定了。。。
Registering
2014-12-11 20:43:28 +08:00
@vileer 可惜这种方式首次加载时,刷新频率太高,会显卡顿
fangzhzh
2014-12-11 20:43:52 +08:00
@vileer 要是很多个item的话,每个图片的load都会刷新,

@Registering 说实话,没看出什么问题,也许问题在cache的load那里.
Registering
2014-12-11 20:49:06 +08:00
@fangzhzh 这两个方法很多时候都不起作用
songwenhai
2014-12-11 23:00:51 +08:00
1.利用setRecyclerListener recycle的view收到loadBitmap回调时不需要再把图片显示出来
2.loadBitmap的回调中不需要调用notifyDataSetChanged,只需要给当前ImageView调用setImageBitmap就可以了
LittleMK
2014-12-13 08:54:42 +08:00
getItem有问题吧?
Registering
2014-12-14 14:07:41 +08:00
@songwenhai
1,setRecyclerListener recycle ???
2,我的做法就是这样的,图片通过一个一个辅助类去下载(带缓存),然后通过一个回调setImageBitmap,并不需要notifyDataSetChanged。。。。。。。就是通过这种方式,出现了图片顺序混乱的情况,
vileer
2014-12-16 13:16:48 +08:00
@Registering 不需要每次getview都去做这样的事情,可以参考google simple里面的slowadapter例子,滚动的时候不加载,挺了的时候才去,最后asyncload的时候可以用线程池,对于快速换出的item不加载,只有真正显示的才去加载
Registering
2014-12-16 13:49:22 +08:00
@vileer 原本我的做法也是滑动时不加载,那样不会出现乱序,,,但是感觉体验不大好

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/153175

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX