Using DiskLruCache in android 4.0 does not provide for openCache method
You can use Picasso as image loader.
Or
This is what I did:
I created a class named DiskLruImageCache with a DiskLruCache (the one from Jake Wharton) object and the same methods in the simple implementation on the dev guide (displaying bitmaps efficiently):
public class DiskLruImageCache {
private DiskLruCache mDiskCache;
private CompressFormat mCompressFormat = CompressFormat.JPEG;
private int mCompressQuality = 70;
private static final int APP_VERSION = 1;
private static final int VALUE_COUNT = 1;
private static final String TAG = "DiskLruImageCache";
public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
CompressFormat compressFormat, int quality ) {
try {
final File diskCacheDir = getDiskCacheDir(context, uniqueName );
mDiskCache = DiskLruCache.open( diskCacheDir, APP_VERSION, VALUE_COUNT, diskCacheSize );
mCompressFormat = compressFormat;
mCompressQuality = quality;
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean writeBitmapToFile( Bitmap bitmap, DiskLruCache.Editor editor )
throws IOException, FileNotFoundException {
OutputStream out = null;
try {
out = new BufferedOutputStream( editor.newOutputStream( 0 ), Utils.IO_BUFFER_SIZE );
return bitmap.compress( mCompressFormat, mCompressQuality, out );
} finally {
if ( out != null ) {
out.close();
}
}
}
private File getDiskCacheDir(Context context, String uniqueName) {
// Check if media is mounted or storage is built-in, if so, try and use external cache dir
// otherwise use internal cache dir
final String cachePath =
Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
!Utils.isExternalStorageRemovable() ?
Utils.getExternalCacheDir(context).getPath() :
context.getCacheDir().getPath();
return new File(cachePath + File.separator + uniqueName);
}
public void put( String key, Bitmap data ) {
DiskLruCache.Editor editor = null;
try {
editor = mDiskCache.edit( key );
if ( editor == null ) {
return;
}
if( writeBitmapToFile( data, editor ) ) {
mDiskCache.flush();
editor.commit();
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "image put on disk cache " + key );
}
} else {
editor.abort();
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + key );
}
}
} catch (IOException e) {
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + key );
}
try {
if ( editor != null ) {
editor.abort();
}
} catch (IOException ignored) {
}
}
}
public Bitmap getBitmap( String key ) {
Bitmap bitmap = null;
DiskLruCache.Snapshot snapshot = null;
try {
snapshot = mDiskCache.get( key );
if ( snapshot == null ) {
return null;
}
final InputStream in = snapshot.getInputStream( 0 );
if ( in != null ) {
final BufferedInputStream buffIn =
new BufferedInputStream( in, Utils.IO_BUFFER_SIZE );
bitmap = BitmapFactory.decodeStream( buffIn );
}
} catch ( IOException e ) {
e.printStackTrace();
} finally {
if ( snapshot != null ) {
snapshot.close();
}
}
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", bitmap == null ? "" : "image read from disk " + key);
}
return bitmap;
}
public boolean containsKey( String key ) {
boolean contained = false;
DiskLruCache.Snapshot snapshot = null;
try {
snapshot = mDiskCache.get( key );
contained = snapshot != null;
} catch (IOException e) {
e.printStackTrace();
} finally {
if ( snapshot != null ) {
snapshot.close();
}
}
return contained;
}
public void clearCache() {
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "disk cache CLEARED");
}
try {
mDiskCache.delete();
} catch ( IOException e ) {
e.printStackTrace();
}
}
public File getCacheFolder() {
return mDiskCache.getDirectory();
}
}
Utils source code is:
public class Utils {
public static final int IO_BUFFER_SIZE = 8 * 1024;
private Utils() {};
public static boolean isExternalStorageRemovable() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
return Environment.isExternalStorageRemovable();
}
return true;
}
public static File getExternalCacheDir(Context context) {
if (hasExternalCacheDir()) {
return context.getExternalCacheDir();
}
// Before Froyo we need to construct the external cache dir ourselves
final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/";
return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
}
public static boolean hasExternalCacheDir() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
}
}
Remember to put
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
on your AndroidManifest.xml
I figured out this way by reading this code and the javadoc from Jake Wharton's DiskLruCache
android DiskLruCache implementation
The signature of the API is a hint that you should read/write from the Cache as if it's an interface to disk. So to answer your question more directly - yes, you should call get() and put() in a thread separate from the main looper.
Always be sympathetic to the user, and don't take more than you need. An appropriate size will depend on the nature of your application. Are you caching a large number of small bitmaps, or a small number of large images? How often do the images change? Are you planning on using an in-memory cache alongside the disk cache? Thinking about these questions will help you come to an appropriate specification that can drive your decision. Alternatively, you can start with a small number (maybe 4mb) and use some logging and/or metrics to measure the amount of cache misses and tweak from there.
Finally, you should specify the number in bytes. E.g.
DISK_CACHE_SIZE = 1024 * 1024 * 16; // 16mb in bytes
Example of JakeWhartons DiskLruCache
I used getBitmap() in the sample someone posted here.
This is the answer you're looking for under a different title. You will have to create a Utils for some of the code but it's pretty straightforward.
Good Luck!
Using DiskLruCache in android 4.0 does not provide for openCache method
Load GridLayout images according to available memory
I've had such problem (need to load more than 100 high-res images to ListView and cache them). I've used DiskLruCache library (https://github.com/JakeWharton/DiskLruCache) for it in a way described here:
Using DiskLruCache in android 4.0 does not provide for openCache method
Works perfectly.
Related Topics
Differencebetween Fragment and Fragmentactivity
An Android App Remembers Its Data After Uninstall and Reinstall
Get the Distance Between Two Geo Points
How to Add Action Bar from Support Library into Preferenceactivity
Android Textview:"Do Not Concatenate Text Displayed with Settext"
How to Auto-Start an Android Application
How to Call a Function After Delay in Kotlin
Android: Can Height of Slidingdrawer Be Set with Wrap_Content
How to Generate Buildconfigfield with String Type
When to Use a Content Provider
How to Programmatically Clear Application Data
Add Views Below Toolbar in Coordinatorlayout
What Do Gc_For_Malloc, Gc_Explicit, and Other Gc_* Mean in Android Logcat
Custom Event Listener on Android App
Application Installation Failed in Android Studio
How to Add Multiple Widgets in the Same App