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

Android开发在使用ListView和GridView时,可能会有很多网络图片需要加载,通常我们会为每个图片加载启动一个Thread或者直接使用官方提供的AsyncTask,来做Http异步加载,但当每个ImageView子视图都触发一个AsyncTask来异步加载图片时,这样就会产生如下问题:

1. 当用户快速滑动时,ImageView已经被回收,而绑定的线程还在运行,浪费CPU,浪费内存。

2. 无法确保当前视图在结束时,分配的视图已经进入循环队列中给另外一个子视图进行重用,意思就是,图片显示错位了,不该显示到当前问题的图片却显示了,这个是经常遇到的问题。可以结合Adapter中的getView方法的convertView参数理解,ListView是回收和重复利用item的。

3. 无法确保所有的异步任务能够按顺序执行。

在这些问题下,官网给出的答案是,使用下面的方法来保证:

1. ImageView和Task绑定准确的加载对应图片;

2. ImageView和Task无法对应时则取消任务;

BitmapFun实现多线程并发加载图片的原理:

一个类,两个方法:

class AsyncDrawable extends BitmapDrawable{...}

boolean cancelPotentialWork(String url, ImageView imageView){...}

ImageViewResizeTask getBitmapWorkerTask(ImageView imageView){...}

具体代码实现如下:

/**
* 扩展BitmapDrawable类,通过弱引用关联任务BitmapWorkerTask
* BitmapDrawable被用来作为占位图片,绑定任务到ImageView中
*/
private class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> viewResizeTaskReference; public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask viewResizeTask) {
super(res, bitmap);
viewResizeTaskReference = new WeakReference<BitmapWorkerTask>(viewResizeTask);
} public BitmapWorkerTask getBitmapWorkerTask() {
return viewResizeTaskReference.get();
}
} /**
* 确保ImageView执行的是它对应的Task,否则取消任务
* @param url
* @param imageView
* @return
*/
private boolean cancelPotentialWork(String url, ImageView imageView) {
// 获得ImageView对应的Task
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (bitmapWorkerTask != null) {
final String imgUrl = bitmapWorkerTask.url;
if (imgUrl == null || !imgUrl.equals(url)) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
} /**
* 获得已经被分配到ImageView的指定的Task
* @param imageView
* @return
*/
private BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}

使用方法:

/**
* 异步加载图片
* @param url
* @param imageView
*/
private void loadBitmap(String url, ImageView imageView) {
if (cancelPotentialWork(url, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable = new AsyncDrawable(context.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(url);
}
} /*
* 异步加载图片Task类
*/
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
... @Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
} if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}

最佳使用实践,提高流畅度

1. 设置ListView的OnScrollListener事件,在滑动的时候不加载图片

public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
if (!Utils.hasHoneycomb()) {
mImageFetcher.setPauseWork(true);
}
} else {
mImageFetcher.setPauseWork(false);
}
}

2. 在Activity或Fragment的onResume(),onPause(),onDestroy()方法中调用恰当方法非常有用

@Override
public void onResume() {
super.onResume();
mImageFetcher.setExitTasksEarly(false);
} @Override
public void onPause() {
super.onPause();
mImageFetcher.setPauseWork(false);
mImageFetcher.setExitTasksEarly(true);
mImageFetcher.flushCache();
} @Override
public void onDestroy() {
super.onDestroy();
mImageFetcher.closeCache();
}

官网

Processing Bitmaps Off the UI Thread

[原]Android官方图片加载利器BitmapFun解析的更多相关文章

  1. Android之图片加载框架Fresco基本使用(二)

    PS:最近看到很多人都开始写年终总结了,时间过得飞快,又到年底了,又老了一岁. 学习内容: 1.进度条 2.缩放 3.ControllerBuilder,ControllerListener,Post ...

  2. Android之图片加载框架Fresco基本使用(一)

    PS:Fresco这个框架出的有一阵子了,也是现在非常火的一款图片加载框架.听说内部实现的挺牛逼的,虽然自己还没研究原理.不过先学了一下基本的功能,感受了一下这个框架的强大之处.本篇只说一下在xml中 ...

  3. Android自定义图片加载框架

    大神原网址: http://blog.csdn.net/lmj623565791/article/details/41874561  思路: 1. 压缩图片 压缩本地图片: 获得imageview想要 ...

  4. Android 平滑图片加载和缓存库 Glide 使用详解

    在图片加载库烂大街的今天,选择一个适合自己使用的图片加载库已经成为了每一个Android开发者的必经之路.现在市面上知名的图片加载库有UIL,Picasso,Volley ImageLoader,Fr ...

  5. android glide图片加载框架

    项目地址: https://github.com/bumptech/glide Glide作为安卓开发常用的图片加载库,有许多实用而且强大的功能,那么,今天就来总结一番,这次把比较常见的都写出来,但并 ...

  6. Android批量图片加载经典系列——使用xutil框架缓存、异步加载网络图片

    一.问题描述 为提高图片加载的效率,需要对图片的采用缓存和异步加载策略,编码相对比较复杂,实际上有一些优秀的框架提供了解决方案,比如近期在git上比较活跃的xutil框架 Xutil框架提供了四大模块 ...

  7. Android批量图片加载经典系列——afinal框架实现图片的异步缓存加载

    一.问题描述 在之前的系列文章中,我们使用了Volley和Xutil框架实现图片的缓存加载(查看系列文章:http://www.cnblogs.com/jerehedu/p/4607599.html# ...

  8. Android 三大图片加载框架的对比——ImageLoader,Picasso,Glide

    一.ImageLaoder介绍 << Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用 多线程下载图片,图片可以来源于网络,文件系统,项目文件夹ass ...

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

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

随机推荐

  1. swift第一季基础语法

    同: 一.基础 同: 1常量和变量 2数据类型和数据类型转换 3别名 不同: 1可选类型optional 2BOOL类型 3元组类型 4断言Assertion 二.基本操作符 同: 1赋值和算术运算及 ...

  2. C#基础之yield与Singleton

    1.实例解析yiled的作用 最近参加java笔试题第一次见到yield这个关键字,既然遇见了那肯定要掌握,下面是C#中关于yield关键字的总结.yield这个关键字作用于迭代器块中,其最本质的功能 ...

  3. java之运算符

    package com.simope.myTest; import java.util.HashMap; import java.util.Iterator; import java.util.Map ...

  4. java并发:获取线程执行结果(Callable、Future、FutureTask)

    初识Callable and Future 在编码时,我们可以通过继承Thread或是实现Runnable接口来创建线程,但是这两种方式都存在一个缺陷:在执行完任务之后无法获取执行结果.如果需要获取执 ...

  5. 第一章 Javscript的数据类型

      任何编程语言,都会讲到数据类型,那么我在这里也简述下Js的数据类型,在js里判断一个变量的数据类型用typeof() 简单数据类型undefined: 代表一切未知的事物,啥都没有,无法想象,代码 ...

  6. 模态窗口插件之Jbox

    $.jBox.tip("报损数量不能大于库存数!", 'error'); $.jBox.tip("请选择要报损的产品", "warn"); ...

  7. [USACO2005][POJ3045]Cow Acrobats(贪心)

    题目:http://poj.org/problem?id=3045 题意:每个牛都有一个wi和si,试将他们排序,每头牛的风险值等于前面所有牛的wj(j<i)之和-si,求风险值最大的牛的最小风 ...

  8. excel导入数据库

    日常工作中,感觉一些基础知识需要做下笔记,可能是刚毕业的缘故吧,还保持着做笔记的习惯,但根据以往经验,纸质笔记最多保持一年,过后想找已是难过登天.电子版笔记感觉很不错,尤其是发布到网络中.笔记内容是本 ...

  9. web前端开发教程系列-1 - 前端开发编辑器介绍

    目录: 前言 一. Webstorm 1. 优点 2. 缺点 3. 教程 4. 插件 5. 技巧 二. SublimeText 1. 优点 2. 缺点 3. 教程 4. 插件 5. 技巧 前言 由于很 ...

  10. Git学习笔记——一个NB的分布式版本控制系统

    1. 命令: git init           创建新仓库 (在一个空文件下然后执行命令) git clone  + 路径      检出仓库,从本地或从服务器上 git status     查 ...