Picasso: Picasso 2.5.2 Caching not working when custom downloader is defined

Created on 1 Nov 2015  路  11Comments  路  Source: square/picasso

I can't get the disk cache to work in Picasso 2.5.2. I have the following relevant dependencies:

com.squareup.picasso:picasso:2.5.2
com.squareup.okhttp:okhttp:2.5.0
com.squareup.okhttp:okhttp-urlconnection:2.5.0

In my application class i am creating an OkHttpClient(), setting the cache and the Picasso instance.

OkHttpClient picassoClient = new OkHttpClient();
picassoClient.interceptors().add(new OAuth2Interceptor());
File cache = CacheUtils.createDefaultCacheDir(this);
picassoClient.setCache(new com.squareup.okhttp.Cache(cache, CacheUtils.calculateDiskCacheSize(cache)));

Picasso picasso = new Picasso.Builder(this)
.defaultBitmapConfig(Bitmap.Config.RGB_565)
.indicatorsEnabled(BuildConfig.DEBUG)
.downloader(new OkHttpDownloader(picassoClient))
.build();

Picasso.setSingletonInstance(picasso);

My CacheUtils class:

public class CacheUtils {
    public static File createDefaultCacheDir(Context context) {
        File cache = new File(context.getApplicationContext().getCacheDir(), "picasso-cache");
        if (!cache.exists()) {
            //noinspection ResultOfMethodCallIgnored
            cache.mkdirs();
        }
        return cache;
    }

    public static long calculateDiskCacheSize(File dir) {
        long size = 5 * 1024 * 1024;
        try {
            StatFs statFs = new StatFs(dir.getAbsolutePath());
            long available = ((long) statFs.getBlockCount()) * statFs.getBlockSize();
            // Target 2% of the total space.
            size = available / 50;
        } catch (IllegalArgumentException ignored) {
        }
        // Bound inside min/max size for disk cache.
       return Math.max(Math.min(size, 50 * 1024 * 1024), 5 * 1024 * 1024);
    }
}

Afterwards i am using Picasso the following way:

Picasso.with(context).load(imageUrl).into(holder.coverImage);

I can't figure out what i am doing wrong but the images does not seem to be loaded from the disk cache. If i close the app and open it again the image is loaded from the network or the memory cache.

If i remove the downloader from the Picasso config then the cache works as expected.

Can anyone help me and tell me what i might be doing wrong?

Most helpful comment

i tried below but it didn't worked.

@PingForward
i tried your solution but it didn't worked for me.
If some one still have this issue try to set cache for OkHttpClient

builder.cache(new Cache(context.getCacheDir(), 25 * 1024 * 1024));

and pass OkHttpClient to OkHttp3Downloader constructor (try to use OkHttp3)

Picasso.Builder builder = new Picasso.Builder(context);
builder.downloader(new OkHttp3Downloader(client));
builder.memoryCache(new LruCache(context));

Also important thing. Add fit() to load request

Picasso.with(context).load(imageUrl).fit().into(holder.coverImage);

i am still facing the same issue when the application is started then the images are fetched and cached by Picasso but when the application is killed and then if i use flight mode and started the app then Picasso is not reloading the images from cache.

All 11 comments

Everything looks fine. How are you determining that the cache isn't working?

Hi Jake,

I am using the indicators which always are green or red, but never yellow.

The following scenario is also indicating that there's a problem.
When the phone is online and an image is loaded correctly, i can close the app, enable airplane mode and then open the app again, then the image is not loaded which i imagine it should be.

Do the images have proper cache headers? Is the interceptor affecting their ability to be cached?

The image request have the following response headers:

Access-Control-Allow-Methods:GET, POST, PUT, DELETE
Cache-Control:public, max-age=604800
Connection:Keep-Alive
Content-Encoding:gzip
Content-Type:text/html
Date:Sun, 01 Nov 2015 13:04:28 GMT
Expires:Sun, 08 Nov 2015 13:04:28 GMT
Keep-Alive:timeout=5, max=99
Server:Apache
Transfer-Encoding:chunked
Vary:Accept-Encoding

And the following request headers:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,da;q=0.6,nb;q=0.4,de;q=0.2,it;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Pragma:no-cache

The interceptor should not affect the ability to cache. The interceptors only responsibility is to check whether the request returns Unauthorized and if so fetch a new token and redo the request.

All of the image request URLs have the following structure:

https://url.com/productName/cover/ID.jpg?scale=540&quality=MED&access_token=ultralongtoken

The parameters of the URL changes over time, but does this affect the caching?

I have the same problem. Is there a solution?

I'm having similar problems too.
Actually no I'm not, I got it sorted out for me after all. Was a silly error in my code.

I don't know what might be the issue with your code, but one thing you might want to do for debugging this sort of things is to change the cache folder to say a publicly available folder on sdcard (or if you have rooted device then I think it's a matter of determining the path to the cache folder and elevating to root access on adb). Then you can easily do something like: adb shell ls /path/to/cache/folder/. Then you can very clearly see if at least something gets added in the cache. Then you know 100% sure if the problem is in mapping your requests to items in cache or are the requests not getting cached at all for some reason.

If at least something gets cached then you should see something like this:
d96b7553455885d16b3153c52872508b.0
d96b7553455885d16b3153c52872508b.1
eb88d72b16a116558a46e3e6625303e7.0
eb88d72b16a116558a46e3e6625303e7.1
f4bbd8d62762b4512cbd9fa23fa04b9d.0
f4bbd8d62762b4512cbd9fa23fa04b9d.1
f59f08c6596868db319b292547549d11.0
f59f08c6596868db319b292547549d11.1
journal

Hi, I have exact the same problem.
I'm using: picasso in ver. 2.5.2 and okhttp ver. 2.7.2
Is there any solution for this problem ?

I have the same problem with okhttp 2.7.5
@timolehto what version of okhttp are you using?

edit:
managed to get it working by setting a custom cache to the OkHttpClient.

OkHttpClient client = new OkHttpClient();
            client.setConnectTimeout(connectTimeOut, TimeUnit.SECONDS);
            client.setReadTimeout(readTime, TimeUnit.SECONDS);

            File cachePath = FuncFileDownload.getStoragePath(context, "pre");
            client.setCache(new com.squareup.okhttp.Cache(cachePath, 30000000));

            sPicasso = new Picasso.Builder(context)
                    .downloader(new OkHttpDownloader(client))
                    .build();
            Picasso.setSingletonInstance(sPicasso);

Hate to pile onto this thread, but this is still an issue with Picasso 2.5.2 + OkHttp 3.4.1. FWIW, here are my response headers:

Age: 287
Connection: keep-alive
Date: Sun, 09 Oct 2016 01:08:42 GMT
Etag: "e218d7b044e2df858e4e8983c8ae2655"
Server: AmazonS3
<omitted some sensitive-looking headers here...>
X-Cache: Hit from cloudfront

@vickychijwani @HolyPick @shamo42 @ilyamuromets

If some one still have this issue try to set cache for OkHttpClient
builder.cache(new Cache(context.getCacheDir(), 25 * 1024 * 1024));
and pass OkHttpClient to OkHttp3Downloader constructor (try to use OkHttp3)

Picasso.Builder builder = new Picasso.Builder(context);
builder.downloader(new OkHttp3Downloader(client));
builder.memoryCache(new LruCache(context));

Also important thing. Add fit() to load request
Picasso.with(context).load(imageUrl).fit().into(holder.coverImage);

i tried below but it didn't worked.

@PingForward
i tried your solution but it didn't worked for me.
If some one still have this issue try to set cache for OkHttpClient

builder.cache(new Cache(context.getCacheDir(), 25 * 1024 * 1024));

and pass OkHttpClient to OkHttp3Downloader constructor (try to use OkHttp3)

Picasso.Builder builder = new Picasso.Builder(context);
builder.downloader(new OkHttp3Downloader(client));
builder.memoryCache(new LruCache(context));

Also important thing. Add fit() to load request

Picasso.with(context).load(imageUrl).fit().into(holder.coverImage);

i am still facing the same issue when the application is started then the images are fetched and cached by Picasso but when the application is killed and then if i use flight mode and started the app then Picasso is not reloading the images from cache.

Was this page helpful?
0 / 5 - 0 ratings