有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Android问题,延迟将图像加载到ListView

这是一种非常常见的场景:在ListView中显示必须从internet下载的图像

现在,我有一个自定义的ArrayAdapter子类,用于ListView。在ArrayAdapter的getView()实现中,我生成了一个单独的线程来加载图像。加载完成后,它会查找相应的ImageView并使用ImageView设置图像。setImageDrawable()。所以我使用的解决方案有点类似于这个:Lazy load of images in ListView

我遇到的问题是,只要我在ImageView上调用setImageDrawable(),ListView就会以某种方式刷新列表中所有当前可见的行!这会产生一种无限循环:

  1. 调用getView()
  2. 生成线程以加载图像
  3. 加载图像;在ImageView上调用setImageDrawable()
  4. ListView出于某种原因选择它并刷新自己
  5. 为了刷新ListView,会为每个可见的行调用getView(),所以我们返回到步骤1,整个过程会自动重复

因此,据我所知,《Android——我如何在ListView中懒洋洋地加载图像》(见上面的链接)中提出的解决方案根本不起作用。它可能看起来像这样,但运行速度非常慢,因为在后台,它会不断重新加载当前可见的行

以前有没有人遇到过这种情况,或者有解决办法


共 (4) 个答案

  1. # 1 楼答案

    我有一个ThumbnailAdapter来总结整个模式,这可能会有所帮助

  2. # 2 楼答案

    我也有同样的问题

    经过将近两天的大量调试/优化,并试图弄清楚为什么在连续使用setImageBitmap()时,我的getView()会一次又一次地被所有视图调用,我想出了一个糟糕的解决方案:

    1)扩展用于列表中所有图像的自定义ImageView

    2)在此ImageView中覆盖该方法

    @Override
    public void requestLayout()
    { 
      return; 
    }
    

    脏兮兮的,但对我来说很管用

    4)利润;)

  3. # 3 楼答案

    我在下面的链接中使用了代码:another stackoverflow question

    为了解决回收问题,我做了一些小改动。我在适配器中将图像的url设置为imageview的标记。以下代码包含我解决回收问题的解决方案:

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView,Drawable drw) {
    
        imageView.setImageDrawable(drw);//drw is default image
        if (drawableMap.containsKey(urlString)) {
            if(imageView.getTag().toString().equals(urlString))
            {
                imageView.setImageBitmap(drawableMap.get(urlString));
                imageView.invalidate();
                return;
            }
    
        }
    
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                BitmapWrapper wrapper = (BitmapWrapper)message.obj;
                if(wrapper.imageurl.equals(imageView.getTag().toString()))
                {
                    imageView.setImageBitmap((Bitmap)wrapper.bitmap);
                    imageView.invalidate();
                }
    
            }
        };
    
        Thread thread = new Thread() {
            @Override
            public void run() {
                //TODO : set imageView to a "pending" image
    
                Bitmap drawable = fetchDrawable(urlString);
                BitmapWrapper wrapper = new BitmapWrapper();
                wrapper.bitmap = drawable;
                wrapper.imageurl = urlString;
                Message message = handler.obtainMessage(1, wrapper);
                handler.sendMessage(message);
            }
        };
        thread.start();
    }
    
    
        public class BitmapWrapper
    {
        public Bitmap bitmap;
        public String imageurl;
    }
    
  4. # 4 楼答案

    在链接的解决方案中,仅当视图尚未具有正确的可绘制图形时,才应调用fetchDrawableOnThread()

    如果getDrawable()返回null,则视图没有可绘制的

    如果要重用插槽,则需要进一步管理状态。例如,如果视图中有一个存储URL的成员变量,以及一个表示是否已加载的布尔值,那么就很容易知道是否要调用fetchDrawableOnThread()

    我推测drawable的toString()详细描述了图像加载的路径。(如果没有,您可以将drawable子类化为returned,使其成为子类)。在这种情况下,您可以避免上面概述的布尔值,只需进行比较,以确定其是否是正确的可绘制的,或者是否要获取替换

    此外,可见行上的getView()应该确保不再可见的行被卸载,以防止内存耗尽。一种巧妙的方法是将不再可见的图像移动到软引用(以便在需要内存时卸载它们),正如原始线程上的另一张海报所指出的那样