java - 位图缩略图的延迟加载列表

标签 java android multithreading

我很难实现延迟加载列表。我知道,有无数关于类似问题的帖子,但请在判断之前看看我的问题。

目标:加载 SD 卡上存在的位图缩略图,但不阻塞主 (UI) 线程,因此列表可以平滑滚动。

来源: 我尝试的基础是这两篇文章:

到目前为止我的尝试:

我试图实现一个类来加载和缓存(我不知道,如果它是适当的表达式)缩略图。它看起来像这样(我尽量不发布代码墙,所以我删除了不重要的部分):

public class ThumbnailContainer
{
    //this will store the thumbnails 
    private final HashMap<File, SoftReference<Bitmap>> data;

    //this Handler class will update the ui, when we got the thumb from a thread
    private static final class BitmapHandler extends Handler
    {
        private final WeakReference<ImageView> image;
        public BitmapHandler(ImageView image) 
            {this.image = new WeakReference<ImageView>(image);}

        @Override
        public void handleMessage(Message msg)
        {
            if(image.get()!=null)
                image.get().setImageBitmap((Bitmap) msg.obj);
        }
    }

    public ThumbnailContainer(Context context)
    {
        data = new HashMap<File, SoftReference<Bitmap>>();
    }

    //this will set the Bitmap to the ImageView (load on a thread if required)
    public void setBitmapOnThread(final File file, final ImageView view)
    {
        //contains will return true, if the data map contains the file key
        //and the SoftReference is still vaild.
        if (contains(file))
        {
            view.setImageBitmap(data.get(file).get());
            return;
        } 
        else
        {
            final Handler handler = new BitmapHandler(view);

            final Thread thread = new Thread()
            {
                @Override
                public void run()
                {
                    Bitmap bitmap = getMeasuredBitmap(file);
                    Message msg = handler.obtainMessage(0, bitmap);
                    handler.sendMessage(msg);
                }
            };

            thread.start();
        }
    }

    // load the Bitmap if it isn't already, scales it down, and recycles the original
    private Bitmap getMeasuredBitmap(File file)
    {
        if (contains(file))
            return data.get(file).get();
        else
        {
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());

            /*counting the scale of the new Bitmap, i cut the detail*/ 

            Bitmap measured = Bitmap.createScaledBitmap(bitmap, w, h, false);
            bitmap.recycle();

            data.put(file, new SoftReference<Bitmap>(measured));

            return measured;
        }
    }

    //returns true, if the map contains this file, and the reference is still valid
    private boolean contains(File file)
    {
        if (data.containsKey(file))
        {
            if (data.get(file).get() != null) return true;
            else return false;
        }
        return false;
    }
}

结果:我的列表滚动仍然非常缓慢。就像我什至没有添加线程解决方案,只是在 listadapters getView() 方法中加载缩略图。我尝试将Threads优先级(请参阅setBitmapOnThread())设置为LOW,当我这样做时,滚动通常是平滑的,并且我可以看到缩略图正在加载,但是当我滚动得非常快时,内存就会耗尽。我认为这是因为启动了太多线程,并且它们无法完成。

我的问题:你们看到这里有明显的错误吗?

如果不是,那么坚持使用低优先级线程解决方案是否明智?如果是这样,那么有没有办法将线程数限制为固定数量(例如 5-6),并且如果达到最大线程数,则在开始新线程之前停止并加入未完成的线程?我读到过有关 ThreadPools 的内容,但我从未使用过。

我非常感谢任何帮助!

最佳答案

我会像你一样停止使用线程并使用 AsyncTask。使用此任务从磁盘获取文件并将其放入缓存中(如果不存在)。将缓存的值返回到适配器中的 ImageView。

因此,在您的适配器中将 ImageView 传递给 AsyncTask。让任务完成工作。

关于java - 位图缩略图的延迟加载列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12318722/

相关文章:

multithreading - 并发调用 `Wait()`的 `sync.Cond`方法,安全吗?

java - 将部分数据标记为超链接、iText

java - 改变内容的顺序辅助 Android 开发的 Eclipse

android - 如何在 Android 中显示 YouTube 视频的缩略图

android - 使用 Android Studio 重命名 Android 包名称

linux - 如何在 Linux 内核中加入一个线程?

java - 在此类的对象上调用 start() 安全吗? Java 并发实践中的一个例子

java 查找并替换 %

java - 如何查找带有特定注释的所有 Java 对象(不是类)?

java - 什么数据类型/类可以让我完成这个任务?