Put a lock on image loading.

This commit is contained in:
Pierre 2018-05-21 09:29:22 +02:00
parent 98713def11
commit 92b2d846bb
2 changed files with 53 additions and 10 deletions

View File

@ -24,17 +24,24 @@ class ImageLoadApplyRunnable implements Runnable {
*/ */
private ImageView imageView; private ImageView imageView;
/**
* Object to notify when the image has been posted
*/
private Object obj = null;
/** /**
* Construct the class * Construct the class
* *
* @param imageView The target image view * @param imageView The target image view
* @param bitmap The bitmap to apply * @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 //Save the values
this.bitmap = bitmap; this.bitmap = bitmap;
this.imageView = imageView; this.imageView = imageView;
this.obj = obj;
} }
/** /**
@ -46,5 +53,11 @@ class ImageLoadApplyRunnable implements Runnable {
//Apply the image //Apply the image
imageView.setImageBitmap(bitmap); imageView.setImageBitmap(bitmap);
synchronized (obj){
//Notify
obj.notifyAll();
}
} }
} }

View File

@ -11,6 +11,7 @@ import org.communiquons.android.comunic.client.data.utils.ImageLoadUtils;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.util.concurrent.locks.ReentrantLock;
/** /**
* Image loading runnable * Image loading runnable
@ -29,6 +30,11 @@ public class ImageLoadRunnable implements Runnable {
*/ */
private static final String TAG = "ImageLoadRunnable"; 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 * 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){ 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 //Check if the list of pending operations has to be initialized or not
if(pendingOperation == null) if(pendingOperation == null)
pendingOperation = new ArrayMap<>(); pendingOperation = new ArrayMap<>();
@ -83,19 +93,18 @@ public class ImageLoadRunnable implements Runnable {
String filename = ImageLoadUtils.IMAGE_CACHE_DIRECTORY + ImageLoadUtils.get_file_name(url); String filename = ImageLoadUtils.IMAGE_CACHE_DIRECTORY + ImageLoadUtils.get_file_name(url);
//Create file object //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 //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 //Check if a file exist or not
if(file.exists()){ if (file.exists()) {
//Then the file can be loaded in a bitmap //Then the file can be loaded in a bitmap
load_image(); safe_load_image();
return; return;
} } else {
else {
//Create the thread and start it //Create the thread and start it
Thread thread = new Thread(new ImageDownloadRunnable(url, file)); Thread thread = new Thread(new ImageDownloadRunnable(url, file));
@ -108,12 +117,12 @@ public class ImageLoadRunnable implements Runnable {
Thread operation = pendingOperation.get(url); Thread operation = pendingOperation.get(url);
//If we couldn't get the thread, this is an error //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 !"); Log.e("ImageLoadManagerRunnabl", "run : Couldn't get thread !");
return; return;
} }
if(operation.isAlive()) { if (operation.isAlive()) {
try { try {
//Wait for the thread to finish //Wait for the thread to finish
operation.join(); operation.join();
@ -127,8 +136,21 @@ public class ImageLoadRunnable implements Runnable {
//Remove the thread from the pending list //Remove the thread from the pending list
pendingOperation.remove(url); 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 the image
load_image(); load_image();
ImageLoadLock.unlock();
} }
/** /**
@ -160,11 +182,19 @@ public class ImageLoadRunnable implements Runnable {
//Delete file //Delete file
file.delete(); file.delete();
return; return;
} }
//Apply the bitmap on the image view (register operation) //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){ } catch (Exception e){
e.printStackTrace(); e.printStackTrace();