Resolving concurrency issues

Fixing android bitmap concurrency problems

Explains the steps involved in fixing concurrency problems when loading bitmaps from AsyncTasks

This tutorial is about resolving concurrency issues that happen when issuing AsyncTasks when using RecyclerViews in android applications.

Get Code

You can download the code from github here https://github.com/mobapptuts/recyclerview_image_gallery.git Tag concurrency

Or else run this command

git clone –branch concurrency https://github.com/mobapptuts/recyclerview_image_gallery.git

Create a class derived from BitmapDrawable

public static class AsyncDrawable extends BitmapDrawable {
        final WeakReference<BitmapWorkerTask> taskReference;

        public AsyncDrawable(Resources resources,
                             Bitmap bitmap,
                             BitmapWorkerTask bitmapWorkerTask) {
            super(resources, bitmap);
            taskReference = new WeakReference(bitmapWorkerTask);
        }

        public BitmapWorkerTask getBitmapWorkerTask() {
            return taskReference.get();
        }
    }

 Add a get BitmapWorkerTask

public static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
        Drawable drawable = imageView.getDrawable();
        if(drawable instanceof AsyncDrawable) {
            AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
            return asyncDrawable.getBitmapWorkerTask();
        }
        return null;
    }

Implement the check BitmapWorkerTask logic

@Override
   public void onBindViewHolder(ViewHolder holder, int position) {
       File imageFile = imagesFile.listFiles()[position];
       Bitmap bitmap = CamaraIntentActivity.getBitmapFromMemoryCache(imageFile.getName());
       if(bitmap != null) {
           holder.getImageView().setImageBitmap(bitmap);
       }
       else if(checkBitmapWorkerTask(imageFile, holder.getImageView())) {
           BitmapWorkerTask bitmapWorkerTask = new BitmapWorkerTask(holder.getImageView());
           AsyncDrawable asyncDrawable = new AsyncDrawable(holder.getImageView().getResources(),
                   placeHolderBitmap,
                   bitmapWorkerTask);
           holder.getImageView().setImageDrawable(asyncDrawable);
           bitmapWorkerTask.execute(imageFile);
       }
   }
public static boolean checkBitmapWorkerTask(File imageFile, ImageView imageView) {
        BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
        if(bitmapWorkerTask != null) {
            final File workerFile = bitmapWorkerTask.getImageFile();
            if(workerFile != null) {
                if(workerFile != imageFile) {
                    bitmapWorkerTask.cancel(true);
                } else {
                    // bitmap worker task file is the same as the imageview is expecting
                    // so do nothing
                    return false;
                }
            }
        }
        return true;
    }

Check in the BitmapWorkerTask onPostExecute method

@Override
  protected void onPostExecute(Bitmap bitmap) {
      if(isCancelled()) {
          bitmap = null;
      }
      if(bitmap != null && imageViewReferences != null) {
          ImageView imageView = imageViewReferences.get();
          BitmapWorkerTask bitmapWorkerTask = ImageAdapter.getBitmapWorkerTask(imageView);
          if(this == bitmapWorkerTask && imageView != null){
              imageView.setImageBitmap(bitmap);
          }
      }
  }

Run & Debug if necessary

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>