Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Picasso 2.5.2 Caching not working when custom downloader is defined #1185

Open
leicht-io opened this issue Nov 1, 2015 · 11 comments
Open

Picasso 2.5.2 Caching not working when custom downloader is defined #1185

leicht-io opened this issue Nov 1, 2015 · 11 comments

Comments

@leicht-io
Copy link

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?

@JakeWharton
Copy link
Member

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

@leicht-io
Copy link
Author

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.

@JakeWharton
Copy link
Member

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

@leicht-io
Copy link
Author

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?

@ilyamuromets
Copy link

I have the same problem. Is there a solution?

@timolehto
Copy link

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

@HolyPick
Copy link

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 ?

@shamo42
Copy link

shamo42 commented Apr 18, 2016

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);

@vickychijwani
Copy link

vickychijwani commented Oct 9, 2016

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 added a commit to vickychijwani/app-of-thrones that referenced this issue Oct 10, 2016
team-pct pushed a commit to popcorn-official/popcorn-android that referenced this issue Nov 24, 2016
* First Android Studio cleanup

* Removed unused imports

* Class structure, fields can be local

* Simplified equals() return

* Java language level migration aids

* Fixed Javadoc issues

* Redundant initializer

* Removed redundant initializers

* Not annotated method overrides method annotated with @nonnull

* Performance issues StringBuilder can be replaced with String

* Statements with empty body

* argsValues is never null

* Improved updater

Simplified logic.
Fixed dereference of 'channel' may produce 'java.lang.NullPointerException'.

* Fixed getPath() may produce 'java.lang.NullPointerException'
Removed unneded try

* Fixed ignored method results

* Use "L"  to indicate a long value

* oneway to interface method

* Removed redundant character escape

* Redundant variable declaration

* Declaration acces can be weaker, changed to private

* Redundant and unused throws clause

* Fixed Javadoc after redundant and unused throws clause fixes

*  Return value of the methods are never used, fixed Javadoc

* Remove unnecessary throws declarations

* Method always return 1

Moved to a public static variable

* CPU_ABI is deprecated, aded compat util classes

* Fixes for locale deprecation

* Fixes for getAllNetworkInfo() deprecation

* Simplified return

* Fix for Settings.System.ANDROID_ID deprecation

* Fix for 'getDrawable(int)' is deprecated

* CPU_ABI is deprecated

* Fix for 'getDrawable(int)' is deprecated

* Fix for deprecated decode

* Removed Locales from compat

Moved to LocaleUtils

* Fixed deprecations for StatFs

* Unused import

* Simplified return

* Boolean method 'isAdded' is always inverted

* Field converted to local

* Performance: used SparseArray instead of HashMap

* Ellipsis string can be replaced with ellipsis character

* Fields requires API level 16 (current min is 15)

* Butterknife update

* Fix apk build

With gradle => 2.2 the apks are generated aligned so we need this changes to assemble the apks correctly to be found by the Jenkins archiving post-built step.

* Java language migration aids

* Unused imports

* Unchecked cast

* Simplified and improved Updater

Using the parser is faster than using a POJO with fromJson

* Jackson as JSON parser

Added dep in build file and POJOS to deserialize the movies JSON, it is tons of times faster than GSON.

* Removed updater POJO

 We parse the JSON directly with the Jackson parser because is very small and simple.

* Removed invalid lines from manifest, meta-data for API < 16 compat

* Removed NameValuePair

* We separate the media response treatment for each media provider

* MediaProvider acts as a really base provider for Media

We move all implementation to the superclass, now the code is more clear.

* Primitive type can not be nullable

* Lazy initialization of subs provider

* Removed GSON dep

* Methods can not be nullable, optional instead

* Simplified catch for all exceptions

* Return the default static navigation index

* member variables to local

* Removed unused method

* Removed unused method, modified access to inner classes

* Modified acces to getVideoPlayerApps to package, format with language

* Simplified catch, modified accesses

* Missing ACCESS_WIFI_STATE permission

* Proper Media.Torrent initialization

* Inheritance is cool

* Removed Created for Javadoc

* Fix for access to member variables

* Known if the app is in debug mode

* Picasso image loading modifications

We use fit instead resize the image, is faster.
We set the default image as the placeholder when loading a new image.

* Better Picasso initialization

* Cancel previous Picasso requests before a new one

* Prevent NPE when no image poster

* Added missing deleted check and URL rewrite for fantart

* Picasso improvements

MemoryPolicy.NO_CACHE - We do not cache images on memory to avoid big memory consumption

centerCrop - Scale the image honoring the aspect ratio until it fills the size. Crop either the top and bottom or left and right so it matches the size exactly.

* Updated butterknife dep for mobile module

* Removed the placeholder due to unexpected results on  scrolling

* debugable != BuildConfig.DEBUG, fixed cacheSize type, increased cache

* Removed unused import

* Removed the custom downloader for Picasso due to cache troubles

square/picasso#1185

* Each provider uses an own tag for request instead of the default

* Each provider cancels their own requests

* We clear old items before change genere.
Member variables to local.
Removed deprecated methods.

* Force the getMediaCallTag method impl for all MediaProvider subclasses

* Fixed deprecation

* Fix #20 Removed genre comparision

To solve the load of not initialized fragments on change genre we always load the results because does not affect performance and ensure that the movies with that genre are loaded into the MediaListFragment when we clicked on the navigation item

* Removed GSON reference

* Fixed onAttach(Activity activity) deprecation warning

* Simplified isLoading return, fixed  getPosition deprecation warning, modified acceses
team-pct pushed a commit to popcorn-official/popcorn-android that referenced this issue Dec 2, 2016
* First Android Studio cleanup

* Removed unused imports

* Class structure, fields can be local

* Simplified equals() return

* Java language level migration aids

* Fixed Javadoc issues

* Redundant initializer

* Removed redundant initializers

* Not annotated method overrides method annotated with @nonnull

* Performance issues StringBuilder can be replaced with String

* Statements with empty body

* argsValues is never null

* Improved updater

Simplified logic.
Fixed dereference of 'channel' may produce 'java.lang.NullPointerException'.

* Fixed getPath() may produce 'java.lang.NullPointerException'
Removed unneded try

* Fixed ignored method results

* Use "L"  to indicate a long value

* oneway to interface method

* Removed redundant character escape

* Redundant variable declaration

* Declaration acces can be weaker, changed to private

* Redundant and unused throws clause

* Fixed Javadoc after redundant and unused throws clause fixes

*  Return value of the methods are never used, fixed Javadoc

* Remove unnecessary throws declarations

* Method always return 1

Moved to a public static variable

* CPU_ABI is deprecated, aded compat util classes

* Fixes for locale deprecation

* Fixes for getAllNetworkInfo() deprecation

* Simplified return

* Fix for Settings.System.ANDROID_ID deprecation

* Fix for 'getDrawable(int)' is deprecated

* CPU_ABI is deprecated

* Fix for 'getDrawable(int)' is deprecated

* Fix for deprecated decode

* Removed Locales from compat

Moved to LocaleUtils

* Fixed deprecations for StatFs

* Unused import

* Simplified return

* Boolean method 'isAdded' is always inverted

* Field converted to local

* Performance: used SparseArray instead of HashMap

* Ellipsis string can be replaced with ellipsis character

* Fields requires API level 16 (current min is 15)

* Butterknife update

* Fix apk build

With gradle => 2.2 the apks are generated aligned so we need this changes to assemble the apks correctly to be found by the Jenkins archiving post-built step.

* Java language migration aids

* Unused imports

* Unchecked cast

* Simplified and improved Updater

Using the parser is faster than using a POJO with fromJson

* Jackson as JSON parser

Added dep in build file and POJOS to deserialize the movies JSON, it is tons of times faster than GSON.

* Removed updater POJO

 We parse the JSON directly with the Jackson parser because is very small and simple.

* Removed invalid lines from manifest, meta-data for API < 16 compat

* Removed NameValuePair

* We separate the media response treatment for each media provider

* MediaProvider acts as a really base provider for Media

We move all implementation to the superclass, now the code is more clear.

* Primitive type can not be nullable

* Lazy initialization of subs provider

* Removed GSON dep

* Methods can not be nullable, optional instead

* Simplified catch for all exceptions

* Return the default static navigation index

* member variables to local

* Removed unused method

* Removed unused method, modified access to inner classes

* Modified acces to getVideoPlayerApps to package, format with language

* Simplified catch, modified accesses

* Missing ACCESS_WIFI_STATE permission

* Proper Media.Torrent initialization

* Inheritance is cool

* Removed Created for Javadoc

* Fix for access to member variables

* Known if the app is in debug mode

* Picasso image loading modifications

We use fit instead resize the image, is faster.
We set the default image as the placeholder when loading a new image.

* Better Picasso initialization

* Cancel previous Picasso requests before a new one

* Prevent NPE when no image poster

* Added missing deleted check and URL rewrite for fantart

* Picasso improvements

MemoryPolicy.NO_CACHE - We do not cache images on memory to avoid big memory consumption

centerCrop - Scale the image honoring the aspect ratio until it fills the size. Crop either the top and bottom or left and right so it matches the size exactly.

* Updated butterknife dep for mobile module

* Removed the placeholder due to unexpected results on  scrolling

* debugable != BuildConfig.DEBUG, fixed cacheSize type, increased cache

* Removed unused import

* Removed the custom downloader for Picasso due to cache troubles

square/picasso#1185

* Each provider uses an own tag for request instead of the default

* Each provider cancels their own requests

* We clear old items before change genere.
Member variables to local.
Removed deprecated methods.

* Force the getMediaCallTag method impl for all MediaProvider subclasses

* Fixed deprecation

* Fix #20 Removed genre comparision

To solve the load of not initialized fragments on change genre we always load the results because does not affect performance and ensure that the movies with that genre are loaded into the MediaListFragment when we clicked on the navigation item

* Removed GSON reference

* Fixed onAttach(Activity activity) deprecation warning

* Simplified isLoading return, fixed  getPosition deprecation warning, modified acceses

* Removed the JsonProperty annotation from getters and setters

* Port to dagger

* Fixed the Url getter for Torrent object

* Fixed setOnTabSelectedListener deprecation warning

* Handle holder visibility if the Item is a VPNNavDrawerItem

* Fixed getColor deprecation warnings

* Added missing nullable import during merge
@thats-bot
Copy link

thats-bot commented Apr 12, 2017

@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);

@andor201995
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants