在列表控件中使用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. Python这些问题你会吗?

    inal作用域的代码一定会被执行吗? 正常的情况下,finally作用域的代码一定会被执行的,不管是否发生异常.哪怕是调用了sys.exit函数,finally也是会被执行的,那怎么样才能让final ...

  2. linux backtrace()详细使用说明,分析Segmentation fault

    linux backtrace()详细使用说明,分析Segmentation fault 在此之前,开发eCos应用程序时,经常碰到程序挂掉后,串口打印输出一大串让人看不懂的数据.今天才明白,原来这些 ...

  3. 用 Vue 做一个简单的购物app

    前言 最近在学习Vue的使用.看了官方文档之后,感觉挺有意思的.于是着手做了一个简单的购物app.h5 与原生 app 交互的原理这是我第一次在这个网站上写分享,如有不当之处,请多多指教. 一整个项目 ...

  4. vue实现双向绑定mvvm

    剖析Vue实现原理 - 如何实现双向绑定mvvm 本文能帮你做什么?1.了解vue的双向数据绑定原理以及核心代码模块2.缓解好奇心的同时了解如何实现双向绑定为了便于说明原理与实现,本文相关代码主要摘自 ...

  5. python中的二进制、八进制、十六进制

    python中通常显示和运算的是十进制数字. 一.python中的二进制 bin()函数,将十进制转换为二进制,0b是二进制的前缀.如: >>> bin(10) '0b1010' 二 ...

  6. PAT 1088. Rational Arithmetic

    For two rational numbers, your task is to implement the basic arithmetics, that is, to calculate the ...

  7. [bzoj3282]Tree_LCT

    Tree bzoj-3282 题目大意:给你n个点m个操作.更改单点权值,加边,删边:查询路径异或和. 注释:$1\le n,m\le 10^5$ 想法:看到了加边删边,果断想到LCT维护.至于路径异 ...

  8. Objective-C学习笔记(二十二)——初始化方法init的重写与自己定义

    初学OC.对init这种方法不是非常了解.我们如今来分别对init方法进行重写以及自己定义,来加深对他的了解. 本样例也是用Person类来进行測试. (一)重写init方法. (1)在Person. ...

  9. UVA10862 - Connect the Cable Wires(递推 + java的大数)

    UVA10862 - Connect the Cable Wires(递推 + java的大数) 题目链接 题目大意:给你n座房子位于一条直线上,然后仅仅给你一个cable service.要求每座房 ...

  10. matlab7安装后的常见问题

    1.有时候.打开MatLab7时,会弹出"找不到指定的模块"对话框,如图(1)所看到的: 图(1) 找不到指定模块 产生这个问题的解决办法是.你的BLAS_VERSION环境变量没 ...