Resolving concurrency issues
July 22, 2015 9:02 am
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
Category: Performance, tutorials
Tags: android, asynctasks, concurrency, development, fixing, how-to, recyclerview, tutorial, tutorials, video