package org.commcare.utils;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.LruCache;
import android.widget.ImageView;
/**
* Class used for managing the LoadImageTasks that load images into a list.
* Ensures that proper caching occurs and attempts to limit overflows
*
* @author wspride
*/
@SuppressLint("NewApi")
public class CachingAsyncImageLoader implements ComponentCallbacks2 {
private final LruCache<String, Bitmap> cache;
private static final int CACHE_DIVISOR = 2;
private final Context context;
public CachingAsyncImageLoader(Context context) {
ActivityManager am = (ActivityManager)context.getSystemService(
Context.ACTIVITY_SERVICE);
int memoryClass = (am.getMemoryClass() * 1024 * 1024) / CACHE_DIVISOR; //basically, set the heap to be everything we can get
this.context = context;
this.cache = new LruCache<>(memoryClass);
}
public void display(String url, ImageView imageView, int defaultResource,
int boundingWidth, int boundingHeight) {
imageView.setImageResource(defaultResource);
Bitmap image;
synchronized (cache) {
image = cache.get(url);
}
if (image != null) {
imageView.setImageBitmap(image);
} else {
new SetImageTask(imageView, this.context, boundingWidth, boundingHeight).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
}
}
/**
* Simple member class used for asyncronously loading and setting ImageView bitmaps
*
* @author wspride
*/
private class SetImageTask extends AsyncTask<String, Void, Bitmap> {
private final ImageView mImageView;
private final Context mContext;
private final int mBoundingWidth;
private final int mBoundingHeight;
public SetImageTask(ImageView imageView, Context context,
int maxWidth, int maxHeight) {
mImageView = imageView;
mContext = context;
mBoundingWidth = maxWidth;
mBoundingHeight = maxHeight;
}
@Override
protected Bitmap doInBackground(String... file) {
return getImageBitmap(file[0]);
}
@Override
protected void onPostExecute(Bitmap result) {
if (result != null && mImageView != null) {
mImageView.setImageBitmap(result);
}
}
public Bitmap getImageBitmap(String filePath) {
Bitmap bitmap = MediaUtil.inflateDisplayImage(mContext, filePath, mBoundingWidth,
mBoundingHeight, true);
if (bitmap != null) {
synchronized (cache) {
cache.put(filePath, bitmap);
}
}
return bitmap;
}
}
/*
* Override these methods to ensure that our overriding behavior is maintained
* through these calls. come from ComponentCallsback2
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
// TODO PLM: this is probably never called because Context.registerComponentCallbacks
// is never used to register instances of CachingAsyncImageLoader
if (level >= TRIM_MEMORY_MODERATE) {
cache.evictAll();
}
}
}