Displaying Bitmaps Efficiently(2)-Processing Bitmaps Off the UI Thread

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).

This lesson walks you through processing bitmaps in a background thread usingAsyncTask and shows you how to handle concurrency issues.

为防止从disk或network获取数据时延迟导致UI线程的阻塞,我们使用AsyncTask来处理图片展示。

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():

class BitmapWorkerTask extends AsyncTask {
    private final WeakReference imageViewReference;
    private int data = 0;

    public BitmapWorkerTask(ImageView imageView) {
        // Use a WeakReference to ensure the ImageView can be garbage collected
        imageViewReference = new WeakReference(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 theAsyncTask does not prevent the ImageView and anything it references from being garbage collected. There’s no guarantee the ImageViewis still around when the task finishes, so you must also check the reference in onPostExecute(). The ImageViewmay no longer exist, if for example, the user navigates away from the activity or if a configuration change happens before the task finishes.

这里使用WeakReference来持有ImageView,这样就不会阻止别的地方对ImageView对象的释放;所以当在AsyncTask中使用ImageView时我们要先判断ImageView是否为空。

To start loading the bitmap asynchronously, simply create a new task and execute it:

public void loadBitmap(int resId, ImageView imageView) {
    BitmapWorkerTask task = new BitmapWorkerTask(imageView);
    task.execute(resId);
}

你可能感兴趣的:(Displaying Bitmaps Efficiently(2)-Processing Bitmaps Off the UI Thread)