译者按: 在Google最新的文档中,提供了一系列含金量相当高的教程。因为种种原因而鲜为人知,真是可惜!Ryan将会细心整理,将之翻译成中文,希望对开发者有所帮助。
本系列是Google关于展示大Bitmap(位图)的官方演示,可以有效的解决内存限制,更加有效的加载并显示图片,同时避免让人头疼的OOM(Out Of Memory)。
【Google官方教程】系列相关阅读: ?where=nkey&keyword=14914
-------------------------------------------------------------------------------------
译文:
在高效地加载Bitmap中,我们讨论了BitmapFactory.decode*系列方法,如果源数据来自硬盘或者网络(或者除内存之外的来源),是不应该在主UI线程执行的。这是因为读取这样的数据所需的加载时间是不确定的,它依赖于多种因素(从硬盘或网络的读取速度、图片的大小、CPU的功率等等)。如果这些任务里面任何一个阻塞了UI线程,系统会将你的应用标记为未响应,并且用户可以选择关闭应用(更多信息,请参阅Designing for Responsiveness)。
这节课将教会你使用AsyncTask在后台线程处理Bitmap并向你展示如何处理并发问题。
使用AsyncTask(异步任务)
AsyncTask类提供了一种简单的方法,可以在后来线程处理一些事情,并将结果返回到UI线程。要使用它,需要创建一个继承于它的子类,并且覆写它提供的方法。这里有一个使用AsyncTask和decodeSampledBitmapFromResource()加载大图片到ImageView中的例子:
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);
}
}
}
}
ImageView的WeakReference(弱引用)可以确保AsyncTask不会阻止ImageView和它的任何引用被垃圾回收器回收。不能保证在异步任务完成后ImageView依然存在,因此你必须在onPostExecute()方法中检查引用。ImageView可能已经不存在了,比如说,用户在任务完成前退出了当前Activity或者应用配置发生了变化(横屏)。
为了异步加载Bitmap,我们创建一个简单的异步任务并且执行它:
public void loadBitmap(int resId, ImageView imageView) {
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(resId);
}