V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Registering
V2EX  ›  程序员

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

  •  
  •   Registering · 2014-12-11 16:32:13 +08:00 · 6105 次点击
    这是一个创建于 3433 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一般使用holder的方式自定义一个adapter,每个节点如果是有图片,则异步加载。

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

    这个问题困扰了几天,没解决,,
    14 条回复    2014-12-16 13:49:22 +08:00
    fangzhzh
        1
    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
        2
    Registering  
    OP
       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
        3
    Registering  
    OP
       2014-12-11 17:23:10 +08:00
    @fangzhzh 没有markdown感觉活不下去了
    vileer
        4
    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
        5
    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
        6
    Registering  
    OP
       2014-12-11 20:40:13 +08:00
    @vileer thx,按你的方法搞定了。。。
    Registering
        7
    Registering  
    OP
       2014-12-11 20:43:28 +08:00
    @vileer 可惜这种方式首次加载时,刷新频率太高,会显卡顿
    fangzhzh
        8
    fangzhzh  
       2014-12-11 20:43:52 +08:00
    @vileer 要是很多个item的话,每个图片的load都会刷新,

    @Registering 说实话,没看出什么问题,也许问题在cache的load那里.
    Registering
        9
    Registering  
    OP
       2014-12-11 20:49:06 +08:00
    @fangzhzh 这两个方法很多时候都不起作用
    songwenhai
        10
    songwenhai  
       2014-12-11 23:00:51 +08:00
    1.利用setRecyclerListener recycle的view收到loadBitmap回调时不需要再把图片显示出来
    2.loadBitmap的回调中不需要调用notifyDataSetChanged,只需要给当前ImageView调用setImageBitmap就可以了
    LittleMK
        11
    LittleMK  
       2014-12-13 08:54:42 +08:00 via Android
    getItem有问题吧?
    Registering
        12
    Registering  
    OP
       2014-12-14 14:07:41 +08:00
    @songwenhai
    1,setRecyclerListener recycle ???
    2,我的做法就是这样的,图片通过一个一个辅助类去下载(带缓存),然后通过一个回调setImageBitmap,并不需要notifyDataSetChanged。。。。。。。就是通过这种方式,出现了图片顺序混乱的情况,
    vileer
        13
    vileer  
       2014-12-16 13:16:48 +08:00
    @Registering 不需要每次getview都去做这样的事情,可以参考google simple里面的slowadapter例子,滚动的时候不加载,挺了的时候才去,最后asyncload的时候可以用线程池,对于快速换出的item不加载,只有真正显示的才去加载
    Registering
        14
    Registering  
    OP
       2014-12-16 13:49:22 +08:00
    @vileer 原本我的做法也是滑动时不加载,那样不会出现乱序,,,但是感觉体验不大好
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3560 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:56 · PVG 12:56 · LAX 21:56 · JFK 00:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.