android 在UI线程之外处理Bitmap - 开发文档翻译
由于本人英文能力实在有限,不足之初敬请谅解
本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接
Processing Bitmaps Off the UI Thread
在UI线程之外处理Bitmap
The BitmapFactory.decode* methods, discussed in the Load Large Bitmaps Efficiently lesson, should not be executed on the main UI thread if the source data is read from disk or a network location (or really any source other than memory).
The time this data takes to load is unpredictable and depends on a variety of factors (speed of reading from disk or network, size of image, power of CPU, etc.).
If one of these tasks blocks the UI thread, the system flags your application as non-responsive and the user has the option of closing it (see Designing for Responsiveness for more information).
以BitmapFactory.decode*开头的方法已经在“Load Large Bitmaps Efficiently”中讨论过了,如果数据源在磁盘或者网络上,那么这些方法不应该在主UI线程中执行
This lesson walks you through processing bitmaps in a background thread using AsyncTask and shows you how to handle concurrency issues.
这里教你如何使用AsyncTask在后台线程中处理bitmap,并且展示如何处理并发问题
Use an AsyncTask
The AsyncTask class provides an easy way to execute some work in a background thread and publish the results back on the UI thread.
To use it, create a subclass and override the provided methods.
Here’s an example of loading a large image into an ImageView using AsyncTask and decodeSampledBitmapFromResource():
使用AsyncTask
AsyncTask类提供一种简单的方式来在后台线程执行一些工作并且把结果发布到UI线程上
为了使用它,建立一个子类,并且覆盖其中的方法
这有一个使用AsyncTask和decodeSampledBitmapFromResource()加载大图片到ImageView的例子
[java]
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);
}
}
}
}
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);
}
}
}
}The WeakReference to the ImageView ensures that the AsyncTask does not prevent the ImageView and anything it references from being garbage collected.
There’s no guarantee the ImageView is still around when the task finishes, so you must also check the reference in onPostExecute().
The ImageView may no longer exist, if for example, the user navigates away from the activity or if a configuration change happens before the task finishes.
关联到ImageView上的WeakReference保证AsyncTask不会阻止ImageView和任何引用它的地方被垃圾回收
当task结束的时候,不保证ImageView仍然存在,所以你也必须在onPostExecute()中检查这个引用
假设例如:用户导航到activity之外或者如果在task结束之前一个配置改变的发生的时候,ImageView也许不复存在
To start loading the bitmap asynchronously, simply create a new task and execute it:
为了异步的加载bitmap,简单的建立一个新的task并且执行它
[java]
public void loadBitmap(int resId, ImageView imageView) {
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(resId);
}
public void loadBitmap(int resId, ImageView imageView) {
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(resId);
}
Handle Concurrency
处理并发
Common view components such as ListView and GridView introduce another issue when used in conjunction with the AsyncTask as demonstrated in the previous section.
In order to be efficient with memory, these components recycle child views as the user scrolls.
If each child view triggers an AsyncTask, there is no guarantee that when it completes, the associated view has not already been recycled for use in another child view. Furthermore, there is no guarantee that the order in which asynchronous tasks are started is the order that they complete.
普通的view组件,例如当ListView 和 GridView与AsyncTask(像上一节展示的那样)一起使用的时候,会引入另外一个问题
为了在内存上的效率,当用户滚动屏幕的时候这些组件回收子view
如果每一个子view都触发一个AsyncTask,那么不保证当它完成的时候,关联的view为了在另一个子view中使用而没有被回收
而且,不保证异步任务开始的顺序与完成
补充:移动开发 , Android ,