JakeWharton's DiskLruCache automatically getting cleared - android

Im using Picasso and okhttp to download and cache images onto the disk.
Im using the below code snippet to set a cache of 10MB to the okhttp client and using it for Picasso.
File folder = new File(context.getCacheDir(),"HomePageCache");
if (!folder.exists())
folder.mkdir();
okHttpClient.setCache(new com.squareup.okhttp.Cache(folder, 1024 * 1024 * 10));
OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient);
picasso = new com.squareup.picasso.Picasso.Builder(context).indicatorsEnabled(true).downloader(okHttpDownloader).build();
This is working perfectly most of the time caching and reloading images even when offline , but the problem is that sometimes it just clears the image cache completely.
I am checking the size of the image cache just to be sure, and it has never crossed 2 MB.
Is there any other reason why my cache is getting cleared?

Like Nikola pointed out in the comment, the cache expire header was responsible for invalidating cached images.

Related

Android Picasso prefetching all images to disk

I want to prefetch images using Picasso and save them all to disk upon opening the app (no lazy loading on the fly). To make sure the cache is big enough I am using the following code in my Application onCreate
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
OkHttpClient client = new OkHttpClient.Builder()
.cache(new Cache(directory, Integer.MAX_VALUE))
.build();
OkHttp3Downloader okHttp3Downloader = new OkHttp3Downloader(client);
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(okHttp3Downloader);
Picasso built = builder.build();
built.setIndicatorsEnabled(false);
built.setLoggingEnabled(false);
Picasso.setSingletonInstance(built);
So here I set my cache size to Integer.MAX_VALUE which should be big enough ;)
I use code similar to this line to prefetch the image: Picasso.with(context).load(url).fetch();.
Now when I kill my internet and mobile data, no images are loaded even though the my code is fetching items. Any ideas why?
Maybe the problem is loosing state. Did you try to extend Application class (like this) and keep Picasso instance here?
In similar situation when I needed to fetch lots of images, I save them to internal memory (not just in some cache) - to prevent from reloading, and save uri's to files into SQLite and then use Picasso to work with such URI's. (don't forget to check that user don't delete anything).
In the end I created my own image manager that downloads and store images (still using picasso to download them).
Here is my approach:
In Application's onCreate method do:
Picasso picasso = new Picasso.Builder(this)
.downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE))
.build();
picasso.setIndicatorsEnabled(BuildConfig.DEBUG);
picasso.setLoggingEnabled(BuildConfig.DEBUG);
Picasso.setSingletonInstance(picasso);
And then wherever you want to load your images call this for each image's url:
Picasso.with(context).load(url).fetch();
From doc:
fetch()
Asynchronously fulfills the request without a ImageView or Target. This is useful when you want to warm up the cache with an image.
You can even pass in callback to check for possible errors

Caching Images and strings using Retrofit, okhttp, picasso

I am working on an app with a lot of dynamic and changing content.
I pull all my data from my server when the app is loading.
As a result, nearly every activity/fragment is loading separately which will cause the user to wait a lot of time for each "page" to load individually.
My goal is to create one loading page when the app starts while being responssible for all the downloading and will disk cache all the images and info(strings) and ti pull them at the right time. (or at least to most of it)
I had the chance to use retrofit, okhttp and Picasso as a single additional library, I know though that they can work together and to be synced and that disk cacheing is available through at least two of this libraries (picasso and okhttp) I'm not sure though which one should do which part and how I can sync them together.
I will appreciate every Tip/Guidance, thanks ahead.
okhttp provides support for cache control headers. I've implemented them in an app before to provide a cache when network is flaky using this guide like so:
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(cacheDirectory, cacheSize);
client = new OkHttpClient.Builder()
.cache(cache)
.build();
As Retrofit uses okhttp internally (if you're using the latest at least), you don't configure any caching for it. Just use the okhttp client you just configured:
RestAdapter restAdapter = new RestAdapter.Builder()
.setClient(new OkClient(client))
.setServer("http://example.com")
...
.build();
Picasso automatically caches images using some default cache size limit. You can change Picasso's default, and I've found some answers here and here. You could set the cache size in the onCreate of your application:
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(new OkHttpDownloader(this,Integer.MAX_VALUE));
Picasso picasso = builder.build();
picasso.setIndicatorsEnabled(true);
picasso.setLoggingEnabled(true);
Picasso.setSingletonInstance(picasso);
Picasso also lets you prefetch images earlier on in an app's lifecycle if you have the time to begin with (say, on a loading screen) and want to make later parts of the app load quicker. To do that, I would use the fetch method from the Picasso builder to get the images, but not insert them into any ImageViews. You can Google it too, but there's a quick answer here which explains the background behind this:
Picasso.with(getApplicationContext())
.load(url)
.fetch();
IIRC you need to make sure you fetch the same sized and transformed image as you try and retrieve later, because Picasso caches the transformed image result rather than the raw downloaded image.

Android Picasso Reload Image from cache fail

Its been sometime I started using Picasso for Image Loading in Android. The usual scenario is , it downloads images and cache it and if later needed it retrieves from Cache.
just found this use case,
if the ImageURL ends with .(jpg,png, etc etc .....)
Ex:http://www.androidguys.com/wp-content/uploads/2014/07/android-for-wallpaper-8.png
Picasso work as expected ,
but if the imageURL's are of type
http://cloud.clubsalive.com.au/download/33/404e58cf-d890-4eaa-981e-c2f3442f9348
then its not reloading from cache , its downloading every time when the view is loaded.
Is it a normal behavior of Picasso ???
Your image is giant. Try to increase cache size. Or scale down your image

volley imageCache and imageRequest both cache the image

i'm using volley to load my images and cache them.
mImageLoader = new ImageLoader(getRequestQueue(context), mImageCache);
which mImageCache is a DiskLruImageCache.
volley fetches images from server by ImageRequest which extend the ImageRequest<Bitmap>
and in request class there is boolean that defines whether to cache the response or not
/** Whether or not responses to this request should be cached. */
private boolean mShouldCache = true;
and ImageRequest hasn't disabled mShouldCache.
as you can see the default value is true so after volley fetches an image caches it under the volley cache directory by diskBasedCache.
so now i have to cache bitmap one from ImageRequest and one from ImageLoader how can i disable ImageRequest cache ? or any other suggestions ?
You are making a mistake giving the ImageLoader a disk cache. Volley already has a shared disk cache for every response, be it an image are not, that works according to HTTP cache headers by default.
You are supposed to provide a memory bitmap cache to the ImageLaoder. Look at the documentation.
The reasoning for it is how Volley is designed. This is the image request logic for Volley:
Image with url X is added to the queue.
Check image memory cache (provided by you) - If available, return bitmap. quickest
Check shared disk cache - If available, check cache headers to see that image is still valid. If valid - add to memory bitmap cache and return. slower, but still pretty quick
This step means that either the image was in the disk cache but its cache headers are missing or expired, or the image wasn't available in the cache at all. Either way, Volley performs a network request and caches the response in both caches. slowest
So by providing a disk cache - you are both slowing down your app and taking up to twice as much disk space with redundant image saving.
Use a memory cache.

Cache Strategy: If in LimitedAgeMemoryCache, load there, else load from web. Fall back to UnlimitedDiscCache on failure

Is it possible to do the above?
My scenario is weather graphics with URLs that remain the same, while the underlying image actually changes. Here are the cases I want to cover:
- Inside the same session of my app (typically 2-5min), I never want to reload the images from the web
- After 15 minutes or so, the image has likely changed, and thus even if I have a cached version, I want to dump it.
- When trying to reload images WHILE OFFLINE, any image (including old) is better than no image, so I want to show it from a disc cache.
Is this setup possible? It didn't seem immediately obvious if its feasible with UIL.
Thanks for the great library!
I think this is solution for you:
File cacheDir = StorageUtils.getCacheDirectory(context); // or any other folder
MemoryCacheAware<String, Bitmap> memoryCacheCore
= new LruMemoryCache(4 * 1024 * 1024); // or any other implementation
MemoryCacheAware<String, Bitmap> memoryCache
= new LimitedAgeMemoryCache<String, Bitmap>(memoryCacheCore, 15 * 60);
DiscCacheAware discCache = new LimitedAgeDiscCache(cacheDir, 15 * 60);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.memoryCache(memoryCache)
.discCache(discCache)
...
.build();
UPD: UIL always search needed image in memory cache at first. Then UIL search it in disc cache. And then it downloads image from network.
If you use "limited age" memory cache or disc cache then bitmap or image file will be deleted from cache after timeout (actually they will be deleted during search in cache).
Logic is following:
Search bitmap in memory cache
needed bitmap is there
bitmap was added to cache more than specified time ago
delete it from memory cache, go to step 2
bitmap was added to cache recently
get the bitmap, display it. End.
no needed bitmap in cache, go to step 2
Search image file in disc cache
needed image is there
image was added to cache more than specified time ago
delete it from disc cache, go to step 3
image was added to cache recently
decode image to bitmap, display it. End.
no needed image in cache, go to step 3
Download image
Don't forget enable caching (in display options, DisplayImageOptions).

Categories

Resources