网站托管什么意思多媒体网页设计教程
news/
2025/10/9 0:25:04/
文章来源:
网站托管什么意思,多媒体网页设计教程,广州冼村的人为什么这么有钱,软文推广文案原文地址#xff1a;http://android.xsoftlab.net/training/displaying-bitmaps/process-bitmap.html
我们在上节课Load Large Bitmaps Efficiently中讨论了BitmapFactory.decode*方法#xff0c;说到了不应该在UI线程中执行读取数据的过程#xff0c;尤其是从磁盘或者网络…原文地址http://android.xsoftlab.net/training/displaying-bitmaps/process-bitmap.html
我们在上节课Load Large Bitmaps Efficiently中讨论了BitmapFactory.decode*方法说到了不应该在UI线程中执行读取数据的过程尤其是从磁盘或者网络上读取数据(或者其它读取速度次于内存的地方)。读取数据的时间是不可预料的这取决于各种各样的因素(从磁盘或者网络读取的速度、图片的大小、CPU的功率,etc.)。如果这其中的一个因素阻塞了UI线程那么系统会标志程序为无响应标志并会给用户提供一个关闭的选项(请查看Designing for Responsiveness获取更多信息)。
这节课讨论了通过使用AsyncTask在非UI线程中处理位图以及展示如何处理并发问题。
使用AsyncTask
类AsyncTask提供了一种简要的方式来处理后台进程的工作并会将处理后的结果推送到UI线程中。如果要使用这个类需要创建该类的子类然后重写所提供的方法。这里有个例子展示了如何使用AsyncTask及decodeSampledBitmapFromResource()来加载一张大图到ImageView上
class BitmapWorkerTask extends AsyncTaskInteger, Void, Bitmap {private final WeakReferenceImageView imageViewReference;private int data 0;public BitmapWorkerTask(ImageView imageView) {// Use a WeakReference to ensure the ImageView can be garbage collectedimageViewReference new WeakReferenceImageView(imageView);}// Decode image in background.Overrideprotected Bitmap doInBackground(Integer... params) {data params[0];return decodeSampledBitmapFromResource(getResources(), data, 100, 100));}// Once complete, see if ImageView is still around and set bitmap.Overrideprotected 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或者在任务结束的时候一些配置发生了变化。
为了启动异步任务来加载图片,需要简单的创建一个新任务并执行它:
public void loadBitmap(int resId, ImageView imageView) {BitmapWorkerTask task new BitmapWorkerTask(imageView);task.execute(resId);
}
处理并发
一些普通的View控件比如ListView和GridView会涉及到另一个问题就是当与AsyncTask结合使用的时候会出现并发问题。为了能有效的使用内存这些控件会随着用户的滑动来回收子View。如果每一个子View都会触发一个AsyncTask那么就不能保障在任务完成的时候与之相关联的View没有被回收利用。此外对于顺序启动的任务也不能保障可以按顺序完成。
博客Multithreading for Performance进一步的讨论了如何处理并发它提供了一个解决方案在ImageView中存储了最近的AsyncTask的引用这个引用可以在任务完成的时候对最近的AsyncTask进行检查。通过类似的办法那么上面章节的AsyncTask可以被扩展成类似的模式。
创建一个专用的Drawable子类来存储工作任务的引用。在这种情况下BitmapDrawable就会被用到所以在任务完成之前可以有一个占位图显示在ImageView上
static class AsyncDrawable extends BitmapDrawable {private final WeakReferenceBitmapWorkerTask bitmapWorkerTaskReference;public AsyncDrawable(Resources res, Bitmap bitmap,BitmapWorkerTask bitmapWorkerTask) {super(res, bitmap);bitmapWorkerTaskReference new WeakReferenceBitmapWorkerTask(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关联上了。如果是这样的话它会通过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 dataif (bitmapData 0 || bitmapData ! data) {// Cancel previous taskbitmapWorkerTask.cancel(true);} else {// The same work is already in progressreturn false;}}// No task associated with the ImageView, or an existing task was cancelledreturn 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 AsyncTaskInteger, Void, Bitmap {...Overrideprotected 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这种会回收它们子View的组件上了简单的调用loadBitmap()就可以正常给ImageView设置图片了。比如在一个GridView的实现中这个方法就可以在相应适配器的getView()方法中使用。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/932087.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!