From 92b2d846bb93ccbd4b5509379e93c794cf3d7e24 Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 21 May 2018 09:29:22 +0200 Subject: [PATCH] Put a lock on image loading. --- .../runnables/ImageLoadApplyRunnable.java | 15 +++++- .../data/runnables/ImageLoadRunnable.java | 48 +++++++++++++++---- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadApplyRunnable.java b/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadApplyRunnable.java index 11a8568..14ca4b2 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadApplyRunnable.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadApplyRunnable.java @@ -24,17 +24,24 @@ class ImageLoadApplyRunnable implements Runnable { */ private ImageView imageView; + /** + * Object to notify when the image has been posted + */ + private Object obj = null; + /** * Construct the class * * @param imageView The target image view * @param bitmap The bitmap to apply + * @param obj Object to notify once the image has been applied */ - ImageLoadApplyRunnable(ImageView imageView, Bitmap bitmap){ + ImageLoadApplyRunnable(ImageView imageView, Bitmap bitmap, Object obj){ //Save the values this.bitmap = bitmap; this.imageView = imageView; + this.obj = obj; } /** @@ -46,5 +53,11 @@ class ImageLoadApplyRunnable implements Runnable { //Apply the image imageView.setImageBitmap(bitmap); + + synchronized (obj){ + //Notify + obj.notifyAll(); + } + } } diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadRunnable.java b/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadRunnable.java index ce8d06b..2012581 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadRunnable.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/runnables/ImageLoadRunnable.java @@ -11,6 +11,7 @@ import org.communiquons.android.comunic.client.data.utils.ImageLoadUtils; import java.io.File; import java.io.FileInputStream; +import java.util.concurrent.locks.ReentrantLock; /** * Image loading runnable @@ -29,6 +30,11 @@ public class ImageLoadRunnable implements Runnable { */ private static final String TAG = "ImageLoadRunnable"; + /** + * Image load lock + */ + public static ReentrantLock ImageLoadLock = null; + /** * An array map with all the pending images associated with their URLs */ @@ -63,6 +69,10 @@ public class ImageLoadRunnable implements Runnable { */ public ImageLoadRunnable(Context context, ImageView imageView, String url){ + if(ImageLoadLock == null) + ImageLoadLock = new ReentrantLock(); + + //Check if the list of pending operations has to be initialized or not if(pendingOperation == null) pendingOperation = new ArrayMap<>(); @@ -83,19 +93,18 @@ public class ImageLoadRunnable implements Runnable { String filename = ImageLoadUtils.IMAGE_CACHE_DIRECTORY + ImageLoadUtils.get_file_name(url); //Create file object - file = new File(mContext.getCacheDir(),filename); + file = new File(mContext.getCacheDir(), filename); //Check no thread is already running for the following image - if(!pendingOperation.containsKey(url)){ + if (!pendingOperation.containsKey(url)) { //Check if a file exist or not - if(file.exists()){ + if (file.exists()) { //Then the file can be loaded in a bitmap - load_image(); + safe_load_image(); return; - } - else { + } else { //Create the thread and start it Thread thread = new Thread(new ImageDownloadRunnable(url, file)); @@ -108,12 +117,12 @@ public class ImageLoadRunnable implements Runnable { Thread operation = pendingOperation.get(url); //If we couldn't get the thread, this is an error - if(operation == null){ + if (operation == null) { Log.e("ImageLoadManagerRunnabl", "run : Couldn't get thread !"); return; } - if(operation.isAlive()) { + if (operation.isAlive()) { try { //Wait for the thread to finish operation.join(); @@ -127,8 +136,21 @@ public class ImageLoadRunnable implements Runnable { //Remove the thread from the pending list pendingOperation.remove(url); + safe_load_image(); + } + + /** + * Load images safely + */ + private void safe_load_image(){ + + Log.v(TAG, "Before lock"); + ImageLoadLock.lock(); + //Load the image load_image(); + + ImageLoadLock.unlock(); } /** @@ -160,11 +182,19 @@ public class ImageLoadRunnable implements Runnable { //Delete file file.delete(); + return; } //Apply the bitmap on the image view (register operation) - imageView.post(new ImageLoadApplyRunnable(imageView, bitmap)); + Object obj = new Object(); + synchronized (obj){ + imageView.post(new ImageLoadApplyRunnable(imageView, bitmap, obj)); + Log.v(TAG, "Locking for " + url); + obj.wait(1000); //Wait for the image to be applied + Log.v(TAG, "Unlocking " + url); + } + } catch (Exception e){ e.printStackTrace();