由于本人英文能力实在有限,不足之初敬请谅解

本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接

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的例子

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并且执行它

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中使用而没有被回收

而且,不保证异步任务开始的顺序与完成时的顺序一致

The blog post Multithreading for Performance further discusses dealing with concurrency, and offers a solution where the ImageView stores a reference to the most recent AsyncTask which can later be checked when the task completes.

Using a similar method, the AsyncTask from the previous section can be extended to follow a similar pattern.

这个blog发布了Multithreading for Performance,更深入的讨论并发的处理,并且提供了一个当任务完成后ImageView将一个引用存储到最近的一个并且之后能被检查的AsyncTask的解决方案

使用一个相似的方法,上一节提到的AsyncTask可以扩展为遵循一个相似的形式

Create a dedicated Drawable subclass to store a reference back to the worker task.

In this case, a BitmapDrawable is used so that a placeholder image can be displayed in the ImageView while the task completes:

建立一个专用的Drawable子类来存储一个关联到工作task的引用

这样,使用了BitmapDrawable,当task完成的时候一个站位的图片就能被显示到ImageView

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();
}
}

Before executing the BitmapWorkerTask, you create an AsyncDrawable and bind it to the target ImageView:

在执行BitmapWorkerTask之前,你可以建立一个AsyncDrawable,并且把它绑定到目标ImageView上面

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);
}
}

The cancelPotentialWork method referenced in the code sample above checks if another running task is already associated with the ImageView.

If so, it attempts to cancel the previous task by calling cancel().

In a small number of cases, the new task data matches the existing task and nothing further needs to happen.

Here is the implementation of cancelPotentialWork:

上面示例中的cancelPotentialWork方法检查是否另一个运行中的task已经关联到这个ImageView

如果是,它试图通过调用cancel()取消前一个任务

少数情况下,新的task数据与已存在的task匹配

下面是cancelPotentialWork的实现

public static boolean cancelPotentialWork(int data, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (bitmapWorkerTask != null) {
final int bitmapData = bitmapWorkerTask.data;
if (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;
}

A helper method, getBitmapWorkerTask(), is used above to retrieve the task associated with a particular ImageView:

上面使用的getBitmapWorkerTask()方法,用来获得与特定的ImageView关联的task

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;
}

The last step is updating onPostExecute() in BitmapWorkerTask so that it checks if the task is cancelled and if the current task matches the one associated with the ImageView:

最后一步是在BitmapWorkerTask中更新onPostExecute(),以便检查这个task是否被取消、当前task是否与关联ImageView的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);
}
}
}
}

This implementation is now suitable for use in ListView and GridView components as well as any other components that recycle their child views.

Simply call loadBitmap where you normally set an image to your ImageView.

For example, in a GridView implementation this would be in the getView() method of the backing adapter.

这种实现适用于ListView 和 GridView组件中,也适用于任何其他回收他们的子view的组件

在你通常给ImageView设置图片的地方简单的调用loadBitmap

例如,在一个GridView实现中,应该在其内部的adapter的getView()方法中调用loadBitmap

原文地址如下,英文水平实在有限,希望拍砖同时能给予指正。

http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

转贴请保留以下链接

本人blog地址

http://su1216.iteye.com/

http://blog.csdn.net/su1216/

android 在UI线程之外处理Bitmap - 开发文档翻译的更多相关文章

  1. 在UI线程之外,多线程处理Bitmaps

    多线程处理Bitmaps     上一篇,我们讨论了:Android有效的处理Bitmap,降低内存 ,可是最好不要运行在主线程(UI线程),假设图片是本地的或者网络的又或者是其它地方的. 图片载入的 ...

  2. android 在你的UI中显示Bitmap - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Displaying Bitmaps in Your UI 在你的UI中显示Bitmap ...

  3. 【Android Developers Training】 57. 在UI线程之外处理图像

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  4. android 缓存Bitmap - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Loading a single bitmap into your user interf ...

  5. android 高效显示Bitmap - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Displaying Bitmaps Efficiently 高效显示Bitmap Lea ...

  6. Android中UI线程与后台线程交互设计的5种方法

    我想关于这个话题已经有很多前辈讨论过了.今天算是一次学习总结吧. 在android的设计思想中,为了确保用户顺滑的操作体验.一 些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必 ...

  7. Android 操作UI线程的一些方法

    我们经常会在后台线程中去做一些耗时的操作,比如去网络取数据.但是当数据取回来,需要显示到页面上的时候,会遇到一些小麻烦,因为我们都知道,android的UI页面是不允许在其他线程直接操作的.下面总结4 ...

  8. Android中UI线程与后台线程交互设计的6种方法

    在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须要重新开启 一个后台线程运行这些任务.然而,往往这些任务最终又会直 ...

  9. 在UI线程之外显示Toast

    new Thread(){ public void run() { Looper.prepare(); Toast t = Toast.makeText(mContext, R.string.cras ...

随机推荐

  1. interrupt_control

    中断的概念CPU在处理过程中,经常需要同外部设备进行交互,交互的方式由“轮询方式”“中断方式” 轮询方式: 方式:在同外设进行交互的过程中,CPU每隔一定的时间状态就去查询相关的状态位,所以在交互期间 ...

  2. django导出excel

    # coding:utf-8 from django.http import HttpResponse from xlwt import * import StringIO, os from test ...

  3. hdu 4403 爆搜

    题意:给一串数字,在其间加入若干加号和一个等号,问使等式成立的方案总数 if the digits serial is "1212", you can get 2 equation ...

  4. 在WAMPSERVER下增加多版本的PHP(PHP5.3,PHP5.4,PHP5.5)完美支持。

    WAMPServer可以让开发者在Windows系统下快速搭建WAMP环境,它支持多版本的Apache.MySQL.PHP之间的相互切换,互不影响,对于PHPer开发者来讲极为方便快速. 以下是在WA ...

  5. oracle开发学习篇之集合运算符以及集合异常捕获

    --取出集合;长度 declare type list_nested ) not null; v_all list_nested := list_nested('a','b','c','d','c', ...

  6. iOS开发里的Bundle是个啥玩意?!

    初学iOS开发的同学,不管是自己写的,还是粘贴的代码,或多或少都写过下面的代码 [[NSBundle mainBundle] pathForResource:@"someFileName&q ...

  7. Spring DAO vs Spring ORM vs Spring JDBC

    Pat 的疑惑 最近关注于 Spring 提供的数据访问技术,对于 Spring 相关的这几个项目有何不同我不是太明白: Spring-DAO (http://docs.spring.io/sprin ...

  8. Arcgis10.5 python按属性分割图层,属性相同分为一个图层

    # coding=utf-8 """ Source code for potential gp tool to create outputs based on attri ...

  9. .Net异步编程 z

    1. 引言 最近在学习Abp框架,发现Abp框架的很多Api都提供了同步异步两种写法.异步编程说起来,大家可能都会说异步编程性能好.但好在哪里,引入了什么问题,以及如何使用,想必也未必能答的上来. 自 ...

  10. 创建新的Cocos2dx 3.0项目并解决一些编译问题

    转载请注明出处:http://blog.csdn.net/cywn_d/article/details/25775019 假设是原来使用cocos2dx 2.x要升级到3.0的项目,可能须要替换coc ...