在UI线程之外,多线程处理Bitmaps
多线程处理Bitmaps
图片载入的时间和很多因素有关(比方从网络或本地读取速度,图片的大小。CPU的能力),假设这些任务堵塞了UI线程,系统有可能会回收并关闭它(see Designing
for Responsiveness for more information).
使用异步任务
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
使用 WeakReference来保存ImageView为了内存可以非常好的回收他们,可是不能保证异步任务结束的时候。该ImageView还存在,所以必须在
public void loadBitmap(int resId, ImageView imageView) {
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(resId);
}
并行处理
为了更好的使用内存,当用户滚动的时候就開始回收其它子View。假设每一个子View都使用一个异步任务。我们不能保证当异步任务结束的时候。相关联的view没有被回收掉。我们也不能保证异步任务依照我们的顺序运行。
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
在运行 BitmapWorkerTask之前。我们能够给ImageView绑定一个AsyncDrawable。
public void loadBitmap(int resId, ImageView imageView) {
if (cancelPotentialWork(resId, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(resId);
}
}
cancelPotentialWork这种方法检查是否有其它任务关联到该ImageView。
假设是的话,我们使用函数cancel()取消掉关联的任务。
非常少情况下,新任务的数据与之前的匹配而且交互。以下是cancelPotentialWork的实现:
public static boolean cancelPotentialWork(int data, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final int bitmapData = bitmapWorkerTask.data;
// If bitmapData is not yet set or it differs from the new data
if (bitmapData == 0 || bitmapData != data) {
// 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;
}
一个辅助方法getBitmapWorkerTask(),用于检索与ImageView相关的任务。
private static 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;
}
最后一步onPostExecute()在BitmapWorkerTask更新为了检验任务是否取消而且检验当前任务是否匹配该ImageView:
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);
}
}
}
}
如今。我们就能使用异步任务非常好的在ListView和GridView里面或者其它组件里面更有效的回收资源。
我们仅仅须要运行loadBitmap 的方法就能放一张图片到ImageVIew里面。
比方,在GridVIew里面,我们在Adapter的getView方法里面使用这样的方法。
关于Bitmap的优化。请看上篇:Android有效的处理Bitmap,降低内存
在UI线程之外,多线程处理Bitmaps的更多相关文章
- android 在UI线程之外处理Bitmap - 开发文档翻译
由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Processing Bitmaps Off the UI Thread 在UI线程之外处 ...
- 【Android Developers Training】 57. 在UI线程之外处理图像
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 在UI线程之外显示Toast
new Thread(){ public void run() { Looper.prepare(); Toast t = Toast.makeText(mContext, R.string.cras ...
- C# 多线程详解 Part.02(UI 线程和子线程的互动、ProgressBar 的异步调用)
我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: private void btnThreadA_Click(object sender, ...
- Android UI线程和非UI线程
Android UI线程和非UI线程 UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这 ...
- 第10讲- UI线程阻塞及其优化
第10讲UI线程阻塞及其优化 .UI 阻塞demo (首先在activity_main.xml中放置两个button,分别命名为button1,button2) //首先设置一个button1用来进行 ...
- android脚步---如何看log之程序停止运行,和UI线程和非UI线程之间切换
经常运行eclipse时,烧到手机出现,“停止运行”,这时候得通过logcat查log了.一般这种情况属于FATAL EXCEPTION,所以检索FATAL 或者 EXCEPTION,然后往下看几行 ...
- Android ActivityThread(主线程或UI线程)简介
1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client ...
- Android Studio学习随笔-UI线程阻塞以及优化
我们在使用手机的时候,经常会遇到一个问题:先是卡死,然后跳出该程序无响应,是否关闭的提示(当然有可能是我们手机性能太差=.=)这是因为线程的阻塞引起的,在这里我讲述一下UI线程,一般处理程序会在UI线 ...
随机推荐
- Patterns-Flyweight
最近在组里讨论设计模式,第一个是享元模式. 自己贴了一篇这个文章:http://www.cnblogs.com/rush/archive/2011/10/01/2197785.html 感觉这篇讲的不 ...
- XML的SelectNodes使用方法以及XPath(转)
XPath 是 XML 的内容,这里 SelectNodes 是 C# 中 XmlDocument 或 XmlNode 的一个方法.SelectNodes 使用 XPath 来选取节点. 重要语法 S ...
- jQuery基本选择 元素
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- 采用QHD分辨率使用kinect2_calibration,完成QHD图像校正
//.................................................................................//采用QHD分辨率使用kinec ...
- golang 的编译安装以及supervisord部署
go的编译 go的编译相对很简单,只需要一个命令即可完成,进入项目开发路径,输入 go install <appName> 即可在bin文件夹下生成可执行文件 appName.此文件可直接 ...
- 解决nginx到后端服务器Connection: close问题
以下是官方原文: By default, NGINX redefines two header fields in proxied requests, “Host” and “Connection”, ...
- linux 安装 登录 centos7
常用资源下载 r.aminglinux.com centos7.aminglinux.com http://www.apelearn.com/study_v2/ 认识linux Debian Slac ...
- DataProtectionConfigurationProvider加密web.config文件
web.config 文件中经常会包含一些敏感信息,最常见的就是数据库连接字符串了,为了防止该信息泄漏,最好是将相关内容加密. Aspnet_regiis.exe命令已经提供了加密配置文件的方法,系统 ...
- 电脑不识别USB blaster驱动问题
电脑不识别USB blaster,如下图: 解决办法:手动更新 http://zhidao.baidu.com/link?url=snVT__AsbtmQ4U5EBVN05Yrgv1TPv7AdVYe ...
- Vivado Logic Analyzer的进一步探讨
本文基于Vivado 2014.2,代码基于文章http://blog.chinaaet.com/detail/37239中使用的代码. 这一篇仅讨论在综合后的Netlist中选择信号进行捕获的方法. ...