Skip to content

Instantly share code, notes, and snippets.

@fada21
Last active March 14, 2018 10:34
Show Gist options
  • Save fada21/10655652 to your computer and use it in GitHub Desktop.
Save fada21/10655652 to your computer and use it in GitHub Desktop.
Disk cache larger size for Picasso OkHttp (use like PicassoBigCache.INSTANCE.getPicassoBigCache(ctx) -> rest as in regular Picasso api .
package com.?
import java.io.File;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.os.StatFs;
import com.squareup.picasso.Downloader;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Picasso.Builder;
import com.squareup.picasso.UrlConnectionDownloader;
public enum PicassoBigCache {
INSTANCE;
private static final String BIG_CACHE_PATH = "picasso-big-cache";
private static final int MIN_DISK_CACHE_SIZE = 32 * 1024 * 1024; // 32MB
private static final int MAX_DISK_CACHE_SIZE = 512 * 1024 * 1024; // 512MB
private static final float MAX_AVAILABLE_SPACE_USE_FRACTION = 0.9f;
private static final float MAX_TOTAL_SPACE_USE_FRACTION = 0.25f;
private Picasso picassoInstance;
private void init(Context ctx) {
if (ctx == null) {
throw new IllegalStateException("Must provide context to init PicassoBigCache!"); // fail fast
}
ctx = ctx.getApplicationContext(); // need application context - activity's context could cause harm
Builder builder = new Picasso.Builder(ctx);
builder.downloader(createBigCacheDownloader(ctx));
picassoInstance = builder.build();
}
public Picasso getPicassoBigCache(Context ctx) {
if (picassoInstance == null) {
synchronized (INSTANCE) {
if (picassoInstance == null)
init(ctx);
}
}
return picassoInstance;
}
static Downloader createBigCacheDownloader(Context ctx) {
try {
Class.forName("com.squareup.okhttp.OkHttpClient");
File cacheDir = createDefaultCacheDir(ctx, BIG_CACHE_PATH);
long cacheSize = calculateDiskCacheSize(cacheDir);
OkHttpDownloader downloader = new OkHttpDownloader(cacheDir, cacheSize);
return downloader;
} catch (ClassNotFoundException e) {
return new UrlConnectionDownloader(ctx);
}
}
static File createDefaultCacheDir(Context context, String path) {
File cacheDir = context.getApplicationContext().getExternalCacheDir();
if (cacheDir == null)
cacheDir = context.getApplicationContext().getCacheDir();
File cache = new File(cacheDir, path);
if (!cache.exists()) {
cache.mkdirs();
}
return cache;
}
/**
* Calculates bonded min max cache size. Min value is {@link #MIN_DISK_CACHE_SIZE}
*
* @param dir
* cache dir
* @return disk space in bytes
*/
static long calculateDiskCacheSize(File dir) {
long size = Math.min(calculateAvailableCacheSize(dir), MAX_DISK_CACHE_SIZE);
return Math.max(size, MIN_DISK_CACHE_SIZE);
}
/**
* Calculates minimum of available or total fraction of disk space
*
* @param dir
* @return space in bytes
*/
@SuppressLint("NewApi")
static long calculateAvailableCacheSize(File dir) {
long size = 0;
try {
StatFs statFs = new StatFs(dir.getAbsolutePath());
int sdkInt = Build.VERSION.SDK_INT;
long totalBytes;
long availableBytes;
if (sdkInt < Build.VERSION_CODES.JELLY_BEAN_MR2) {
int blockSize = statFs.getBlockSize();
availableBytes = ((long) statFs.getAvailableBlocks()) * blockSize;
totalBytes = ((long) statFs.getBlockCount()) * blockSize;
} else {
availableBytes = statFs.getAvailableBytes();
totalBytes = statFs.getTotalBytes();
}
// Target at least 90% of available or 25% of total space
size = (long) Math.min(availableBytes * MAX_AVAILABLE_SPACE_USE_FRACTION, totalBytes * MAX_TOTAL_SPACE_USE_FRACTION);
} catch (IllegalArgumentException ignored) {
// ignored
}
return size;
}
}
@fada21
Copy link
Author

fada21 commented Apr 14, 2014

Instead of:
Picasso.with(context)
use:
PicassoBigCache.INSTANCE.getPicassoBigCache(ctx)

@mstfchelik
Copy link

hello fada

unfortunately its not working. this codes caching but if i dont have connection, it does not display cached images. I have a viewpager that presents some latest info about one company. I use your PicassoBigCache class to cache images. It seems its caching but when i turn off internet connection and reopen app. Its not displaying images from local. can you please help me for it ?

thx

@fada21
Copy link
Author

fada21 commented Oct 29, 2014

Hi @mstfchelik

What device are you testing on?
It seems that you enabled INTERNET permission but you also have to enable WRITE_EXTERNAL_STORAGE (please double check if that's the right one, thanks).

And watch for cache size, I've made it xxl.

@Jackcar
Copy link

Jackcar commented Nov 26, 2014

Hello fada,

It didn´t work for me too. I enabled INTERNET permission and WRITE_EXTERNAL_STORAGE too, but when I kill the app and reopen without network, it doesn't display any images.

Can you help me, please?

@quangson91
Copy link

Hi fada,
I think we can use OkhttpDownloader to custom cache location & size is better. ^^
https://square.github.io/picasso/javadoc/com/squareup/picasso/OkHttpDownloader.html

@vijaykd
Copy link

vijaykd commented Aug 31, 2015

Hi fada,

Thanks for quick help on how to cache using Picasso, the cache is happening but the images are not getting loaded from cache if they are offline. How do I load them from cache?

@Kolyall
Copy link

Kolyall commented Jan 29, 2016

Does you code work with last version of Picasso?

@vialyx
Copy link

vialyx commented May 17, 2016

Great solution! Thanks a lot!

@jonneymendoza
Copy link

Does this cache the images for offline use indefinitely?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment