在使用ViewHolder模式的ListView中远程加载图片

7

主要问题:

在使用ViewHolder模式的简单ListView适配器中,什么是最高效、无bug的远程图片懒加载方法?

我目前的实现方式是首先检查一个SoftReference位图HashMap,查找是否有该图片的软缓存版本。如果失败,则检查硬缓存中是否有该图片的副本。如果再次失败,就从网络上获取。我将所有这些操作都放在一个单独的线程和队列中,以消除并发或重复下载。

问题出现在通过回调函数进行加载时。由于我使用了ViewHolder模式,我的视图不断被回收利用,我没有找到一种可靠的方法来消除不同的图片随机附加到我的ImageViews上的情况。每次加载之前,我会默认显示一张默认图片,但由于视图被如此快速地回收利用,“旧”的监听器会应用到我的ImageView上,提供错误的图片,然后被正确的图片替换掉。

我唯一找到的半靠谱的解决方案是使用ViewHolder本身作为监听器,但这只能使问题不那么明显。在快速滚动时仍然会出现问题。

任何帮助都将不胜感激。

更新:

https://github.com/DHuckaby/Prime


这对我也是一个很烦人的问题,有时候会强制我不使用回收机制(牺牲性能以换取更好的用户体验,不看到交换的图像)。如果你解决了这个问题并且发布自己的答案,我会很感激的,并给你点赞 :) 如果我发现任何东西,我也会发布出来。 - momo
我看到了同样糟糕的行为。在 Android 的另一个领域中,系统本身并没有提供帮助,而是强制每个用户从头开始重新实现解决方案。大多数人在第1-5次迭代中失败。是的,我有点像 Android 狂热者。 - Heiko Rupp
1个回答

6

我已经找到了一个解决图片切换问题的方法,并在下面提供了一段代码。不过,我还没有接受它,因为我不知道这是否是最有效的方法,这是我最初的问题。如果实现正确,它将完美地工作。

 public void getView(int position, View convertView, ViewGroup parent) {

     ViewHolder holder;
     if (convertView == null) {

     ...

     String imagePath = insertImageUrlHere();
     Object tag = holder.userThumb.getTag();
     if (tag != null && tag.equals(imagePath)) {
          // Do nothing
     } else {
          holder.userThumb.setTag(imagePath);
          holder.userThumb.setImageResource(R.drawable.default_image);
          AsynchronousImageLoadingUtility.load(imagePath, holder);
     }

     ...

     return convertView;
 }

 private static class ViewHolder implements AsynchronousImageLoadingUtilityCallback {

     private ImageView userThumb;

     @Override
     public void onImageLoad(String source, Bitmap image) {
          if (image != null && userThumb.getTag().equals(source)) {
               userThumb.setImageBitmap(image);
          }
     }
 }

是的,它确实可以。自发布此帖以来,我已经将该模式构建成了一个更好的实用程序,链接在这里:https://github.com/DHuckaby/Prime - HandlerExploit
@HandlerExploit 你能把你的代码粘贴在这里吗?因为上面的代码没有完整的 if (convertView == null) - Hunt
你能否请看一下这个链接:https://dev59.com/ZGfWa4cB1Zd3GeqPgV1O - Hunt
很棒的解决方案,对我来说也可以。 - Dani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接