How to implement my own disk cache with picasso library - Android? - android

I'm using picasso library to load images for my app. But I don't how to implement my own disk (sdcard) caching with picasso library.

Picasso uses the HTTP client for disk caching and if one is already configured it will use that instead of installing its own.
For the built-in UrlConnection the docs for installing a cache are here: https://developer.android.com/reference/android/net/http/HttpResponseCache.html
If you are using OkHttp then you just call setCache:
http://square.github.io/okhttp/2.x/okhttp/com/squareup/okhttp/OkHttpClient.html#setCache-com.squareup.okhttp.Cache-

#Dax, to save files in custom cache directory using OkHttp, I would code something like this -
OkHttpClient okHttpClient = new OkHttpClient();
File customCacheDirectory = new File(Environment.getExternalStorageDirectory().getAbsoluteFile() + "/MyCache");
okHttpClient.setCache(new Cache(customCacheDirectory, Integer.MAX_VALUE));
OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient);
Picasso picasso = new Picasso.Builder(mainActivity).downloader(okHttpDownloader).build();
picasso.load(imageURL).into(viewHolder.image);
Hope this helps.

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.

Picasso doesn't cache image on disk

I have to use custom OkHttpClient so I can add headers to the image requests. The problem is Picasso won't cache any images on disk because of this. I've used setIndicatorsEnabled(true) to check caching and I see only red indicators. When I use default OkHttpDownloader all is ok. Below is my Picasso initialization code. So does anyone encounter the same problem?
public static void init(Context context) {
Picasso.Builder builder = new Picasso.Builder(context);
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new AuthInterceptor());
Downloader downloader = new OkHttpDownloader(client);
Picasso.setSingletonInstance(builder.downloader(downloader).build());
Picasso.with(context).setIndicatorsEnabled(true);
}
Also my image download code
public static void load(final ImageView imageView, final Image image) {
Picasso.with(imageView.getContext())
.load(image.getUrl())
.resize(400, 0)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.into(imageView);
}
Ah since this is happening when you change headers, you are most probably not setting the Cache-Control header
According to Jake wharton (One of the developer of Picasso)
Picasso doesn't have a disk cache. It delegates to whatever HTTP
client you are using for that functionality (relying on HTTP cache
semantics for cache control). Because of this, the behavior you seek
comes for free
Taken from Jake Wharton's answer here
Also,
If you never see a blue indicator, it's likely that your remote images
do not include proper cache headers to enable caching to disk

Picasso with OkHttp?

How to write picasso with Okhttp?
My code is given below but it is showing Error. By the way I am having confusion that picasso uses by default OkHttp or should I write it in code also?
OkHttpClient okHttpClient = new OkHttpClient();
RestAdapter restAdapter = new RestAdapter.Builder().setClient(new OkClient(okHttpClient)).build();
OkHttpDownloader downloader = new OkHttpDownloader(okHttpClient);
Picasso picasso = new Picasso.Builder(context).downloader(downloader).build();
Picasso.with(context).load("http://192.168.0.15:1337/offers/" + image_url.get(position)).resize(350, 100).centerCrop().into(holder.imageView);
No, you don't need to do things like that. OkHttp is a thing, which just make HTTP connection and loading files, for example, JSON easier. You should use it in separate thread, otherwise, you'll get an NetworkOnMainThreadException.
If you just need to download image, you won't need specific HTTP connection. Just use Picasso, for example, in onCreate() of the Activity, and enjoy the result.
All you need to do is:
Picasso.with(context)
.load("http://192.168.0.15:1337/offers/" + image_url.get(position))
.resize(350, 100)
.centerCrop()
.into(holder.imageView);

Loading images using picasso on a slow connection

I am using Picasso to load images for a listview.
The problem is internet connection is slow.
How can I change load timeout time in Picasso?
My code is :
Picasso.with(context)
.load(MainActivity.WEBSITE + book_item.Image)
.resize(final_thumb_width, final_thumb_height)
.into(new PicassoTarget(book_item,item.img, item.title));
You could possibly try something like this in your MainActivity's onCreate (or whereever you want to create the Picasso Builder
Picasso picasso;
OkHttpClient okHttpClient;
okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
picasso = new Picasso.Builder(this)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
That should give Picasso a timeout of ten seconds. Configure it to your needs.
Full Disclosure: I don't use a timeout. I just noticed this in the API. This may be completely wrong lol.
You have two options:
Subclass a Downloader class. Check this for reference implementation
Preconfigure OkHttpClient with timeouts and pass it to Picasso

Categories

Resources