您的位置:首页 > 移动开发 > Android开发

Android异步加载图片(一)下载完图片之后,如何更新界面

2015-03-02 20:08 274 查看

场景

想象一下加载图片的时候,ImageView首先设置一个placeHolder,然后开启AsyncTask去加载合适的图片,图片加载成功之后, 怎么去更新ImageView?一般来讲,有两种处理方式,第一种:将ImageView传递给AsyncTask,task执行完之后,直接ImageView设置bitmap,第二种:Task执行完毕之后,将Bitmap存储在缓存里,通知主线程的view,进行数据更新。

将ImageView传递给AsyncTask

要求

ListView或者GridView会复用ImageView,例如pos为4的ImageView4开启了一个AsyncTask,用户滚动到了pos为8的位置,复用了ImageView4,即使这个时候AsyncTask更新完了,但是也不能去更新ImageView4。

AsyncTask不能阻止ImageView的内存释放,例如当用户离开这个页面的时候,应该销毁界面,AsyncTask应当避免造成内存泄露

AsyncTask执行完毕之后,应该能够拿到ImageView,并且ImageView设置Bitmap之前需要判断ImageView与Drawable和Task之间必须一一对应

实现

BitmapWorkerTask继承AsyncTask,弱引用ImageView,这样AsyncTask既可以在执行完毕之后取到ImageView更新Bitmap,又不会阻止ImageView被释放

ImageView每次都会设置一个placeHolder AsyncDrawable,在AsyncDrawable中弱引用AsyncTask,当AsyncTask执行完毕,可以通过ImageView get AsyncDrawable,然后通过AsyncDrawable获取到BitmapTask,判断task是否是同一个task,如果是,那么就能确定ImageView,AsyncDrawable,AsyncTask一一对应,可以进行数据更新,此外AsyncTask完全执行完毕之后,也可以直接被释放掉了,AsyncDrawable不会阻碍AsyncTask被释放

Task执行完毕之后,将Bitmap存储在缓存里,通知主线程的view,进行数据更新

缺点:

盲目刷新,效率太低,特别是ImageView特别多,AsyncTask执行很快,那么刷新的频率会特别高,这样会导致页面不断刷新,甚至卡顿

总结

ImageView,BitmapWorkerTask,AsyncDrawable的关系

BitmapWorkerTask持有一个WeakReference imageViewReference,弱引用ImageView,用作异步处理加载图片的任务。

AsyncDrawable巧妙的引用持有弱引用WeakReference bitmapWorkerTaskReference,AsyncDrawable继承自BitmapDrawable,这样ImageView就可以setImageBitmap(AsyncDrawable)

AsyncDrawable中弱引用BitmapWorkerTask,ImageView.getDrawable又可以获得AsyncDrawable,继而获得BitmapWorkerTask

关键代码

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

protected class BitmapWorkerTask extends AsyncTask<Object, Void, BitmapDrawable> {
private Object data;
private final WeakReference<ImageView> imageViewReference;

public BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}

final AsyncDrawable asyncDrawable =
new AsyncDrawable(mResources, map, task);
imageView.setImageDrawable(asyncDrawable);

protected void onPostExecute(BitmapDrawable value) {
final ImageView imageView = getAttachedImageView();
if (value != null && imageView != null) {
imageView.setImageDrawable(value);
afterGetBitmap(imageView, value);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐