• 图片加载AsyncTask并发问题


    在列表控件中使用AsycnTask加载图片时,会带来并发问题。

    如果每个子视图都触发一个AsyncTask,因为AsyncTask内部是一个线程池,并发触发时,不能确保每个子视图的AsyncTask都进入了队列,而且异步任务的完成顺序和启动顺序也不一定一致。

    Multithreading For Performance这篇文章提供了一种方法。

    主要方案如下:

    1. 通过定制一个BitmapDrawable,让ImageView储存当前AsyncTask的引用(弱引用)

      BitmapLoadTask,一个加载图片的AsyncTask,可以执行从网络、文件加载图片

    class AsyncDrawable extends BitmapDrawable {
        private final WeakReference<DownloadTask> downloadTaskWeakReference;
        
        AsyncDrawable(BitmapLoadTask downloadTask) {
            this.downloadTaskWeakReference = new WeakReference<>(downloadTask);
        }
        public DownloadTask getDownloadTask() {
            return downloadTaskWeakReference.get();
        }
    }
    
    1. ListView显示一个ImageView,并开始下载之前,判断是否有另一个AsyncTask已经与该ImageView绑定

      1. 如果存在一个Task,并且它的任务就是当前ImageView的任务,则不会新建一个AsyncTask去下载
      2. 如果不存在,或者存在的任务执行的下载不同于当前的任务,就取消当期的Task,然后新建一个。

      下载时判断:

        public void loadBitmap(String url, ImageView imageView) {
            if (shouldNewTaskToLoad(url, imageView)) {
                final BitmapLoadTask bitmapLoadTask = new BitmapLoadTask(imageView);
                final AsyncDrawable asyncDrawable = new AsyncDrawable(bitmapLoadTask);
                imageView.setImageDrawable(asyncDrawable);
                bitmapLoadTask.execute(url);
            }
        }
    ```java
        
        判断的逻辑:
    ```java
    public static boolean shouldNewTaskToLoad(String url, ImageView imageView) {
            if (imageView != null) {
                AsyncDrawable asyncDrawable = (AsyncDrawable) imageView.getDrawable();
                if (asyncDrawable != null) {
                    BitmapLoadTask bitmapLoadTask = asyncDrawable.getDownloadTask();
                    if (bitmapLoadTask != null) {
                        //如果当前要下载的图片的地址与ImageView中储存的Task下载的地址不想等
                        if (url == null || (!url.equals(bitmapLoadTask.url))) {
                            bitmapLoadTask.cancel(true);
                        } else {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
    
    1. 使用:在加载图片时:使用setImageDrawable将AsyncTask与ImageView关联
        if (shouldNewTaskToLoad(url, imageView)) {
           final BitmapLoadTask bitmapLoadTask = new BitmapLoadTask(imageView);
           final AsyncDrawable asyncDrawable = new AsyncDrawable(bitmapLoadTask);
           imageView.setImageDrawable(asyncDrawable);
           bitmapLoadTask.execute(url);
            }
    
  • 相关阅读:
    MOSS 2010 修改管理员密码 欧阳锋
    MOSS2010 中“找不到位于xxxx的web应用程序”的解决办法 欧阳锋
    MSSQL 2008 无法修改表问题的解决 欧阳锋
    不是每个在你身上拉屎的都是你的敌人 欧阳锋
    笑一笑 欧阳锋
    隐藏MOSS2010 左边的导航 欧阳锋
    爱情与婚姻的区别 欧阳锋
    两年后,我们怎么办
    C#控件的闪烁问题解决方法总结
    Linux内核编译配置过程
  • 原文地址:https://www.cnblogs.com/jiy-for-you/p/7282029.html
Copyright © 2020-2023  润新知