在非UI线程处理Bitmap
来源:互联网 发布:mac上推荐的文艺软件 编辑:程序博客网 时间:2024/05/22 09:05
这个貌似是google相册的源码的一部分,网上copy的,作者是对谷歌官方文档进行翻译(感谢作者),仔细研究,真的不得不佩服老外,值得学习
转自:http://www.linuxidc.com/Linux/2012-11/73937p2.htm
常见的View(视图)组件如ListView和GridView在于AsyncTask配合使用的时候引出了另外一个问题,这个我们在上一节中提到过。为了提升内存效率,当用户滚动这些组件的时候进行子视图的回收(主要是回收不可见的视图)。如果每个子视图都触发了一个AsyncTask,无法保证在任务完成的时候,关联视图还没有被回收而被用来显示另一个子视图。此外,也无法保证异步任务结束的循序与它们开始的顺序一致。
Multithreading for Performance这篇文章深入讨论了如何处理并发问题,并且给出了如何在任务结束的时候检测ImageView存储最近使用的AsyncTask引用的解决方案。使用相似的方法,可以遵循类似的模式来扩展前面的AsyncTask。
创建一个专用的Drawable之类,用来存储worker task的引用。在这种情况下,任务结束的时候BitmapDrawable可以取代图像占位符显示在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(); }}
在执行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); }}
在上面的代码示例中引用的cancelPotentialWork方法可以检测一个执行中的任务是否与ImageView有关联。如果有关联,它将通过调用canceel()方法试图取消之前的任务。在少数情况下,新的任务中的数据与现有的任务相匹配,因此不需要做什么。下面是calcelPotentialWork的具体实现:
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;}
一个助手方法,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;}
最后一步是更新BitmapWorkerTask中的onPostExecute()方法,以便检测与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以及其他任何需要回收子视图的组件中。当你只需要为ImageView设置图片,调用loadBitmap就可以了。例如,在GridView中实现的方式是在Adapter的getView()方法中。
- 在非UI线程处理Bitmap
- 在非UI线程处理Bitmap
- 在非UI线程处理Bitmap
- 在非UI线程处理Bitmap(实用)
- 在非UI线程处理Bitmap
- 在非UI线程中处理Bitmap
- 非UI线程处理Bitmap
- 非UI线程处理Bitmap
- 非UI线程处理Bitmap
- 第二课:在非UI线程处理Bitmap
- android 非UI线程处理Bitmap
- 非UI线程处理Bitmap(官方文档)
- Processing Bitmaps Off the UI Thread [在非UI线程处理Bitmap]
- 在UI线程外处理Bitmap
- 【Google官方教程】第二课:在非UI线程处理Bitmap
- 【Google官方教程】第二课:在非UI线程处理Bitmap
- 【Google官方教程】第二课:在非UI线程处理Bitmap
- 【Google官方教程】第二课:在非UI线程处理Bitmap
- 【Android】定时以及循环触发事件的实现
- SpringMVC简单流程
- oracle truncateb表后 表空间释放问题的解决办法
- supervisor - Python进程管理工具
- S3C2440 SDRAM内存驱动
- 在非UI线程处理Bitmap
- group by rollup 和grouping的使用实例
- Android手机通过socket与pc通信
- 数据库
- QT线程(一):线程类
- g++编译器为什么不报错呢?
- 电源管理
- js弹出窗口总结6种弹窗方法
- QT线程(二)---线程同步