标签:android listview 并发 asynctask
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI 线程中创建
2) execute方法必须在UI 线程中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。
4) 该task只能被执行一次,否则多次调用时将会出现异常
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {ImageView的WeakReference引用确保了这个AsyncTask不会阻碍ImageView以及它所关联的任何引用的垃圾回收。不保证在task完成的时候ImageView仍然是存在的(没有被回收),所以必须要在onPostExecute()方法中检查是否为空。ImageView可能不会一直存在,例如,如果用户离开了当前的Activiy,或者在task完成前屏幕发送了旋转等。为了能够异步的开始加载bitmap,简单的创建一个先的task并开始执行:
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);
}
}
}
}
public void loadBitmap(int resId, ImageView imageView) {处理并发
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(resId);
}
static class AsyncDrawable extends BitmapDrawable {在执行BitmapWorkerTask之前,创建一个AsyncDrawable并且把它绑定到ImageView上:
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();
}
}
public void loadBitmap(int resId, ImageView imageView) {上面代码使用的cancelPotentialWork()方法检查了是否有另一个运行中的task关联了这个ImageView。如果是,它会尝试调用cancle()方法取消前面的task:
if (cancelPotentialWork(resId, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(resId);
}
}
public static boolean cancelPotentialWork(int data, ImageView imageView) {getBitmapWorkerTask()方法返回跟imageview相关的task:
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 data
if (bitmapData == 0 || 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;
}
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {最后一步就是在onPostExecute()方法中进行更新:
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {以上的实现就可以被应用的ListView和GridView这种控件中了。只要简单的调用loadBitmap方法就行了。例如,有一个GridView应该在它的Adapter的getView()方法中使用loadBitmap()方法。
...
@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);
}
}
}
}
标签:android listview 并发 asynctask
原文地址:http://blog.csdn.net/kent_todo/article/details/43528075