在列表控件中使用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);
}

图片加载AsyncTask并发问题的更多相关文章

  1. [原]Android官方图片加载利器BitmapFun解析

    通过BitmapFun在项目中使用,结合代码了解一下BitmapFun加载图片的原理,以及最佳使用实践.本文说明不包括BitmapFun的缓存部分. Android开发在使用ListView和Grid ...

  2. Android中常见的图片加载框架

    图片加载涉及到图片的缓存.图片的处理.图片的显示等.而随着市面上手机设备的硬件水平飞速发展,对图片的显示要求越来越高,稍微处理不好就会造成内存溢出等问题.很多软件厂家的通用做法就是借用第三方的框架进行 ...

  3. imagepool前端图片加载管理器(JavaScript图片连接池)

    前言 imagepool是一款管理图片加载的JS工具,通过imagepool可以控制图片并发加载个数. 对于图片加载,最原始的方式就是直接写个img标签,比如:<img src="图片 ...

  4. Android图片加载库:最全面的Picasso讲解

    前言 上文已经对当今 Android主流的图片加载库 进行了全面介绍 & 对比 如果你还没阅读,我建议你先移步这里阅读 今天我们来学习其中一个Android主流的图片加载库的使用 - Pica ...

  5. 一起写一个Android图片加载框架

    本文会从内部原理到具体实现来详细介绍如何开发一个简洁而实用的Android图片加载缓存框架,并在内存占用与加载图片所需时间这两个方面与主流图片加载框架之一Universal Image Loader做 ...

  6. Android项目框架之图片加载框架的选择

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 从Android爆发以后,自定义的控件如EditTextWithDelete.ActionBar.P ...

  7. Android批量图片加载经典系列——采用二级缓存、异步加载网络图片

    一.问题描述 Android应用中经常涉及从网络中加载大量图片,为提升加载速度和效率,减少网络流量都会采用二级缓存和异步加载机制,所谓二级缓存就是通过先从内存中获取.再从文件中获取,最后才会访问网络. ...

  8. Android Handler 异步消息处理机制的妙用 创建强大的图片加载类(转)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 最近创建了一个群,方便大家交流,群号: ...

  9. 图片加载之Picasso使用

    简介 Picasso是Square公司开源的一个Android图形缓存库,可以实现图片下载和缓存功能. 主要有以下一些特性: 在Adapter中回收和取消已经不在视野范围图片资源的加载,防止可能出现的 ...

随机推荐

  1. redis得配置及使用

    http://www.cnblogs.com/huskyking/p/6004772.html

  2. commons.dbutils 的使用列子

    c0p3的导入请参考前文 https://www.cnblogs.com/appium/p/10183016.html JdbcUtils: package cn.itcast.jdbc; impor ...

  3. 复习MySQL⑤查询、常用函数

    查询操作符列表 distinct操作符:用来消除重复记录. - 例: 查询fruits表中所有不重复的s_id select distinct s_id from fruits; 子查询:写在()中, ...

  4. 单调队列 && 单调栈

    单调队列 && 单调栈 单调队列 维护某个滑动区间的min or max,可用于dp的优化 以维护min为例,采用STL双端队列实现 每次加入元素x前 先检查队首元素==滑动后要删除的 ...

  5. 微信小程序-蓝牙连接

    最近的项目需要使用小程序的蓝牙功能与硬件设备进行连接相互传送数据指令,联调过程中发现一些问题,于是想着记录下来,方便以后查看! 1.0一般使用蓝牙功能肯定是想连接某一个蓝牙设备,所以需要知道这个蓝牙设 ...

  6. leetcode 188-maxProfit

    public static int maxProfit(int k, int[] prices) { if (0 >= k || null == prices || 1 >= prices ...

  7. 移动端rem.js使用方法

    下面的代码一是我根据rem的使用经验,自己写的一个rem.js,发现很好用,能适用所有移动端h5页面的自适应需求: 代码一: ``` window.onload = function(){ /*720 ...

  8. Golang - 流程控制

    目录 Golang - 流程控制 1. 选择结构 2. 循环结构 3. 跳转语句 Golang - 流程控制 1. 选择结构 if else语句: //package 声明开头表示代码所属包 pack ...

  9. mybatis传入两个String类型的参数

    1.项目spring +mybatis +oracle 2.报错信息: [DEBUG] -- :: org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debu ...

  10. 使用idea创建maven项目时 需要注意的问题

    截几张图来说明吧 上面的红色框如果不选中  将来创建的工程中没有webapp目录以及下面的子目录 选中之后  然后一直“下一步”  直到工程创建 但是我第一次按照正确的方式操作时  工程中并没有src ...