Non-UI line loads download image

Source: Internet
Author: User

Processing Bitmaps off the UI thread non-UI thread loads download picture

Bitmapfactory.decode* a series of methods, as discussed in the previous article on efficient loading of large graphs.
If the data source of the picture is a disk, or the network (somewhere other than memory), the method of parsing the picture should not be executed in the UI thread. The amount of time these data load tasks take is many factors that are not controllable (e.g., disk read speed, picture size, CPU frequency, etc.) if these tasks block the UI thread, the system determines that your application is unresponsive and the user has the right to shut down your software, which is a very bad user experience.

This article is mainly used to explain how to use Asynctask to handle the picture loading process and the processing of concurrency problems in a background thread.

Use of an asynctask using Asynctask

Asynctask This class makes it easier to process certain tasks in the background, and then returns the results to the UI thread after the task has been processed. The way to use it is to write a subclass of the method that covers Asynctask. Here is an example of loading a picture into ImageView via the Asynctask and Decodesampledbitmapfromresource () method:

  class Bitmapworkertask extends Asynctask<integer, Void, bitmap> {private final weakreference< imageview> imageviewreference;private int data = 0;public Bitmapworkertask (ImageView ImageView) {//Use a WEAKREF Erence to ensure the ImageView can be garbage collected imageviewreference = new Weakreference<imageview> (image  View);  }//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); }    }  }}

This weak reference to the ImageView (WeakReference) ensures that the Asynctask object does not prevent the ImageView and referenced ImageView objects from being reclaimed by the garbage collection mechanism. When the Asynctask task is finished, there is no guarantee that ImageView still exists, so you must check the reference in the OnPostExecute () method. This imageview may not last long, such as when the user exits the current activity, or the configuration environment changes after the task is completed.

The task of implementing an asynchronous load picture requires just a new task and then execute.

public void loadBitmap(int resId, ImageView imageView) {    BitmapWorkerTask task = new BitmapWorkerTask(imageView);    task.execute(resId);}
Handle Concurrency dealing with concurrency problems

Some common view components, the ListView and the GridView, combined with asynctask to present the contents of the current chapter, raise a series of questions. To efficiently use memory, these controls recycle the child control view object when the user slides the screen. If the view object of each sub-class triggers a asynctask, there is no guarantee that when the Asynctask task is finished, the associated View object has not been recycled to show the other view.

It does not guarantee the consistency of the start and end order of the asynchronous task.

This blog discusses multithreading for performance to solve concurrency problems and provides a workaround.

Create a drawable subclass to store a reference to a worker task. In this case, the bitmapdrawable can be used. That way, when the background task finishes executing, the image's container placeholer can display the image in 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();    }}

Before executing the bitmapworkertask, you need to create a asyncdrawable and then bind it to the target's 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);  }}

This cancelpotentialwork method can check if the ImageView in the example code above has more than one running task. (In fact, is to verify that a imageview is only a background task to run, to avoid a imageview binding multiple background tasks, resulting in a waste of resources)
If it is, the current task is canceled by the Cancel () method. In fact, in a few cases, even if you find a new background task with the previous duplicate, but will not cancel out the new task. The following is the implementation of this method.

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 data        //      if (bitmapData == 0 || bitmapData != data) {            //取消当前任务          // Cancel previous task          bitmapWorkerTask.cancel(true);      } else {          // The same work is already in progress          return false;      }  }    //当前ImageView没有其他的任务与它关联,或则有其他的任务与他关联但是已经取消掉了  // No task associated with the ImageView, or an existing task was cancelled  return true;}

There is also a help method that Getbitmapworkertask used to get the task associated with this 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; }

The final step is to update (upload) the OnPostExecute () method in Bitmapworkertask to check whether the current task is canceled and associated with the 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);             }        }    }}

This implementation class is now easy to use in the ListView and GridView. Some other components that need to reclaim sub-category View can also use this class.

When you need to set an image for ImageView, simply call LoadBitmap this method to achieve a complex background load task.

For example, in the GridView implementation of this process can be in the background adapter in the GetView () method to modify.

For the complete implementation class of this example, see Guo Lin's blog post.

Non-UI line loads download image

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.