Declarative Cache Control API #438

Closed
JakeWharton opened this Issue Mar 12, 2014 · 36 comments

Projects

None yet
@JakeWharton
Member

I've been sitting on this for a while as a future feature but hadn't documented it.

The API would allow specifying a cache interaction policy both "downward" on the load and "upward" back through the processing. Through this you can facilitate complex cache interactions for both valid and seemingly-questionable use cases.

Random subset of interactions from other issues:

  • Skip memory cache "downward" only.
  • Skip memory cache "upward" only.
  • Load from local cache (memory or disk) only.
  • Force re-load from network.

I'm not going to do a full-on API strawman, but I know we'll probably want some EnumSet action with

public enum BitmapSource { MEMORY, DISK, NETWORK }
public enum BitmapSink { MEMORY, DISK }

This API will trump the existing weak skipCache() method on RequestCreator.

@dnkoutso dnkoutso added this to the Picasso Next milestone Mar 12, 2014
@TequilaZhang

Hi:
Support for force reloading,now? Thank you..
I think your code is very amazing,but sometiomes I want to clear the cache (memory and disk), reload from cloud.Could you tell me a way to do that?

@JakeWharton
Member

Not yet. No.

On Sun, Mar 30, 2014 at 10:26 PM, TequilaZhang notifications@github.comwrote:

Hi:
Support for force relosding,now?

Reply to this email directly or view it on GitHubhttps://github.com/square/picasso/issues/438#issuecomment-39054917
.

@TequilaZhang

Hi:
will you update it or not later?

@ovy9086
ovy9086 commented Mar 31, 2014

is work on this started on a branch? or after 2.3 release?

@JakeWharton
Member

Not yet started.

On Mon, Mar 31, 2014 at 3:28 PM, Ovidiu Latcu notifications@github.comwrote:

is work on this started on a branch? or after 2.3 release?

Reply to this email directly or view it on GitHubhttps://github.com/square/picasso/issues/438#issuecomment-39150220
.

@dnkoutso
Collaborator

After 2.3.

@Queatz
Queatz commented May 22, 2014

We need this, buddy.

@dnkoutso dnkoutso modified the milestone: Picasso 2.4, Picasso Next May 27, 2014
@dnkoutso
Collaborator

Moved to 2.4. This will be a good new feature for 2.4.

@dnkoutso
Collaborator
dnkoutso commented Jul 8, 2014

This will be scoped (and most likely implemented) for 2.4.

First thing is scroll listener based loading.

@odedregev

+1

In the mean time the following line of code will force download from network:
//force no proxy cache by appending a random number to the image url
String imageurl = person.getImageUrl() + "?t=" + System.currentTimeMillis();

@jfyles
jfyles commented Aug 1, 2014

That works, but then it caches it that that throwaway url as the key, so it'll reload for each individual one. We absolutely need to be able to invalidate any cache on demand. Is there an updated timeline on this?

@JakeWharton
Member

No timeline.
On Aug 1, 2014 9:46 AM, "Justin Fyles" notifications@github.com wrote:

That works, but then it caches it that that throwaway url as the key, so
it'll reload for each individual one. We absolutely need to be able to
invalidate any cache on demand. Is there an updated timeline on this?


Reply to this email directly or view it on GitHub
#438 (comment).

@jfyles
jfyles commented Aug 1, 2014

How does Square manage profile photos then? Is there any mechanism for a user changing a profile image? We store ours on S3 with a hash of the user ID (hence the cache issues if the image is changed but the path isn't) - we could store it with an arbitrary guid, but we'd lose the simplicity of the implementation. Any input would be greatly appreciated!

@MFlisar
MFlisar commented Aug 1, 2014

The workaround works and even can be extended... Save the url with the timestamp and whenever you want to invalidate a cached image, update the time of the url...

PS: Here is another workaround (that can be extended, but works with simple urls for example): http://stackoverflow.com/questions/22243417/android-picasso-clear-cache/24001131#24001131

@JakeWharton
Member

Allow caching forever and change the URL when the image changes.

@masermb
masermb commented Aug 5, 2014

Concerning temporary workaround mentioned by MichaelFlisar. How can I save the url with the timestamp and then update that timestamp to invalidate a cached image file? I have tried linux touch command on image files from my local apache server public directory, manipulating both access and modification time with no success. Please help.

@odedregev

The cache invalidation should take place on the client side and not on
the server. When the image is updated on the server, find a way to tell
that to the client via some API or some other methodology (maybe every
week) and when you want to be sure you retrieve the request from the server
(and not use the local cache on the client side) just request the image
again with the suffix "?time=42342342342" (the number should be now in unix
time).

if the image url is:
https://pbs.twimg.com/media/BsdGwVYCYAAikFX.jpg

request:
https://pbs.twimg.com/media/BsdGwVYCYAAikFX.jpg?time=42342342342

On Tue, Aug 5, 2014 at 11:14 PM, masermb notifications@github.com wrote:

Concerning temporary workaround mentioned by MichaelFlisar. How can I save
the url with the timestamp and then update that timestamp to invalidate a
cached image file? I have tried linux touch command on image files from my
local apache server public directory, manipulating both access and
modification time with no success. Please help.


Reply to this email directly or view it on GitHub
#438 (comment).

Oded Regev
Head of Mobile
FTBpro.com http://ftbpro.com/ | Facebook http://www.facebook.com/ftbpro
| LinkedIn http://www.linkedin.com/company/ftbpro

The largest fan-generated media platform in global football. mobile first!

@masermb
masermb commented Aug 6, 2014

Thank you odedregev! That's what I wanted! Adding time request value allows me to force Picasso to load image from network instead of cache.

@rothschild86

It would be awesome to see this:

public enum BitmapSource { MEMORY, DISK, NETWORK }
public enum BitmapSink { MEMORY, DISK }

@afarriaga

Hi, has this feature been implemented or do we still need to use the workaround suggested above (by MichaelFlisar)? Thanks.

@JakeWharton
Member

Current best candidate:

picasso.load('http://example.com/')
  .cachePolicy(NO_CACHE, NO_STORE)
  .networkPolicy(NO_CACHE, NO_STORE, OFFLINE)
  .into(imageView);

enum MemoryPolicy {
  NO_CACHE, NO_STORE
}
enum NetworkPolicy {
  NO_CACHE, NO_STORE, OFFLINE
}

This will be what's implemented unless anyone has other thoughts.

@rothschild86

Awesome to see progress on this. What's the difference between NO_CACHE and NO_STORE?

@JakeWharton
Member

One is reading, the other is writing, respectively.

On Thu, Dec 11, 2014, 6:52 PM rothschild86 notifications@github.com wrote:

Awesome to see progress on this. What's the difference between NO_CACHE
and NO_STORE?


Reply to this email directly or view it on GitHub
#438 (comment).

@rothschild86

ah. nice.

@dnkoutso dnkoutso modified the milestone: Picasso 2.5, Picasso Next Dec 12, 2014
@JakeWharton JakeWharton closed this in #821 Jan 5, 2015
@jvcjunior

Sorry if this question is silly.
I am loading images from disk. When I remove the file from gallery the image still loads. What should I do to invalidate this image or clean this specific image from cache? I don't understand how to do it using MemoryPolicy or NetworkPolicy.

@dnkoutso
Collaborator

Read MemoryPolicy and NetworkPolicy JavaDoc.

picasso.load(url).memoryPolicy(NO_CACHE).networkPolicy(NO_CACHE) to force the request to reload from the network.

There is also clearKeyUri in Cache you can use to evict the image from the memory cache.

@Karlooie
Karlooie commented Mar 9, 2015

Hello,
I'm facing a problem with network policy.

my code to reload an image from network is:

            Picasso.with(MainActivity.this).load(url)
                    .networkPolicy(NetworkPolicy.NO_CACHE)
                    .memoryPolicy(MemoryPolicy.NO_CACHE)
                    .into(mPicassoTg);

note: mPicassoTg is a field of my main activity, so I hope it's not garbage collected.

behavior:
mPicassoTg.onBitmapLoaded is NOT CALLED. (nor is onBitmapFailed)
mPicassoTg.onPrepareLoad is called

Everything works fine if I remove networkPolicy setter,
It works also on a new image, that is not in the cache (network is working and url is correct).

            Picasso.with(MainActivity.this).load(url)
                    .memoryPolicy(MemoryPolicy.NO_CACHE)
                    .into(mPicassoTg);

Am I missing something?
need more details?

Thank you for the great Picasso and all the support,
Carlo

@oliverhausler

I want to use disk cache, but not cache any images in memory (in order to keep memory consumption low), but as it looks

.memoryPolicy(MemoryPolicy.NO_STORE)

implicitly applies NetworkPolicy.NO_STORE as well. Is this a bug or can I get around this? Does my approach of reducing memory consumption make sense at all?

@JakeWharton
Member

Just set a Cache instance which does nothing. Then you don't have to worry
about including those options on every call.

On Sat, Apr 11, 2015, 2:43 PM oliverhausler notifications@github.com
wrote:

I want to use disk cache, but not cache any images in memory (in order to
keep memory consumption low), but as it looks

.memoryPolicy(MemoryPolicy.NO_STORE)

implicitly applies NetworkPolicy.NO_STORE as well. Is this a bug or can I
get around this? Does my approach of reducing memory consumption make sense
at all?


Reply to this email directly or view it on GitHub
#438 (comment).

@oliverhausler

I'm not worried about calling this on every call, I want to use disk cache, but not memory cache. Is that possible and does that make sense at all? (I am handling many large images, which are not accessed often, so I want to cache them on disk, but not in memory. GC is slow sometimes and my app crashes due to high memory consumption, even though I have removed all my references already. So I wanted to have the least load on memory possible.)

[I'm also trying to work around #972]

@JakeWharton
Member

Picasso only has a memory cache so making it no-op won't affect the disk
caching (which lives in the HTTP client).

I can look into the cache API behavior later.

On Sat, Apr 11, 2015, 2:53 PM oliverhausler notifications@github.com
wrote:

I'm not worried about calling this on every call, I want to use disk
cache, but not memory cache. Is that possible and does that make sense at
all? (I am handling many large images, which are not accessed often, so I
want to cache them on disk, but not in memory. GC is slow sometimes and my
app crashes due to high memory consumption, even though I have removed all
my references already. So I wanted to have the least load on memory
possible.)


Reply to this email directly or view it on GitHub
#438 (comment).

@mrafieej

@JakeWharton
I am having memory issues also. could you please elaborate on what the right way to set a Cache instance is? Thanks!

@mrafieej

Also invalidate is not working for me some reason. I am calling it like this (called from an activity):
Picasso.with(this).invalidate(image_url);
I want to load the new image when the user uploads a new one, but it is not working for some reason... I would appreciate any comments on that as well.

@rjcristy
rjcristy commented May 3, 2015

I have the same problem with @mrafieej . When I use invalidate after the basic method of loading an image, somewhere during the application, the images don't show anything (since there is no error image, which is fine to me),

I am trying any codes posted here but no luck. A detail of the problem is this: when the user changes the image from another device or platform (Web browser, or in an IOS device), it doesn't update the image in the android app. Can you help me? Thanks!

@danieljanes

How would we use this to cache images only for the lifetime of a component (Fragment, ViewGroup, ...)?
Use case: We have a fragment with a grid of images which should be cached for the lifetime of the fragment. When the user navigates away from and back to the fragment we want the images to reload.

@omid-nazifi

Hi, I wanna cache images in memory by Picasso but I have a problem for reloading. Is it possible changing an image when its resource has changed in server. In other words, when network is off, used from cached image in memory and when network is On check the URL, If resource has changed then reload image. if not use a previous image.
Please let me know it is possible or not? And How can I do it?

Thanks

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