How to use disk caching in Picasso?

I use Picasso to display an image in an Android application:

/** * load image.This is within a activity so this context is activity */ public void loadImage (){ Picasso picasso = Picasso.with(this); picasso.setDebugging(true); picasso.load(quiz.getImageUrl()).into(quizImage); } 

I have debugging capability and always displays both red and green. But yellow is never displayed

Now, if I upload the same image the next time, and the Internet is not available, the image does not load.

Questions:

  • Does the cache have a local drive?
  • How to enable disk caching, since I will use the same image several times.
  • Do I need to add a disk to the Android manifest file?
+112
android caching image picasso
Jun 01 '14 at 10:19
source share
8 answers

This is what I did. Works good.

First add OkHttp to the Gradle assembly file of the application module:

 compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.squareup.okhttp3:okhttp:3.10.0' compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' 

Then create a class extending Application

 import android.app.Application; import com.jakewharton.picasso.OkHttp3Downloader; import com.squareup.picasso.Picasso; public class Global extends Application { @Override public void onCreate() { super.onCreate(); Picasso.Builder builder = new Picasso.Builder(this); builder.downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE)); Picasso built = builder.build(); built.setIndicatorsEnabled(true); built.setLoggingEnabled(true); Picasso.setSingletonInstance(built); } } 

add it to the manifest file as follows:

 <application android:name=".Global" .. > </application> 

Now use Picasso as usual. Without changes.

EDIT:

if you want to use only cached images. Call the library like this. I noticed that if we do not add networkPolicy, the images will not be displayed when fully launched, even if they are cached . The code below solves the problem.

 Picasso.with(this) .load(url) .networkPolicy(NetworkPolicy.OFFLINE) .into(imageView); 

EDIT No. 2

The problem with the above code is that if you clear the cache, Picasso will continue to search for it in the cache offline and will fail, in the following code example, the local cache is considered, if it is not found in offline mode, it connects to the network and replenishes the cache.

 Picasso.with(getActivity()) .load(imageUrl) .networkPolicy(NetworkPolicy.OFFLINE) .into(imageView, new Callback() { @Override public void onSuccess() { } @Override public void onError() { //Try again online if cache failed Picasso.with(getActivity()) .load(posts.get(position).getImageUrl()) .error(R.drawable.header) .into(imageView, new Callback() { @Override public void onSuccess() { } @Override public void onError() { Log.v("Picasso","Could not fetch image"); } }); } }); 
+222
Jun 06 '15 at 19:56
source share

1) the answer to the first question: according to the Picasso Method for the With () method

The default Picasso global instance returned by () is automatically initialized to the default values โ€‹โ€‹that suit most implementations.

  • 15% LRU cache available RAM
  • Cache with a capacity of 2% memory up to 50 MB, but not less than 5 MB.

But Disk Cache operation for global By default Picasso is only available in API 14+

2) the answer to the second question: Picasso use an HTTP client request for Disk Cache operation So , you can make your own http request header Cache-Control property with max-age And create your own instance of Static Picasso instead of the standard Picasso. Using

1] HttpResponseCache (Note: only works for API 13+)
2] OkHttpClient (works for all APIs)

Example for using OkHttpClient to create your own Static Picasso class:

  • First create a new class to get your own singleton Picasso object

     import android.content.Context; import com.squareup.picasso.Downloader; import com.squareup.picasso.OkHttpDownloader; import com.squareup.picasso.Picasso; public class PicassoCache { /** * Static Picasso Instance */ private static Picasso picassoInstance = null; /** * PicassoCache Constructor * * @param context application Context */ private PicassoCache (Context context) { Downloader downloader = new OkHttpDownloader(context, Integer.MAX_VALUE); Picasso.Builder builder = new Picasso.Builder(context); builder.downloader(downloader); picassoInstance = builder.build(); } /** * Get Singleton Picasso Instance * * @param context application Context * @return Picasso instance */ public static Picasso getPicassoInstance (Context context) { if (picassoInstance == null) { new PicassoCache(context); return picassoInstance; } return picassoInstance; } } 
  • use your own singleton Picasso object instead of Picasso.With()

PicassoCache.getPicassoInstance(getContext()).load(imagePath).into(imageView)

3) the answer to the third question: you do not need any disk permissions for operations with the disk cache

Links : Github problem about disk cache , @ jake-wharton โ†’ Question1 and Question2 answered two questions

+45
Dec 11 '14 at 11:25
source share

For caching, I would use OkHttp hooks to gain control over the caching policy. Check out this example, which is included in the OkHttp library.

RewriteResponseCacheControl.java

Here is how I would use this with Picasso -

 OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.networkInterceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); return originalResponse.newBuilder().header("Cache-Control", "max-age=" + (60 * 60 * 24 * 365)).build(); } }); okHttpClient.setCache(new Cache(mainActivity.getCacheDir(), Integer.MAX_VALUE)); OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient); Picasso picasso = new Picasso.Builder(mainActivity).downloader(okHttpDownloader).build(); picasso.load(imageURL).into(viewHolder.image); 
+21
Oct 20 '15 at 17:10
source share

1) Picasso has a cache by default (see ahmed hamdy answer)

2) If you really need to take an image from the disk cache and then the network, I recommend writing your own bootloader:

 public class OkHttpDownloaderDiskCacheFirst extends OkHttpDownloader { public OkHttpDownloaderDiskCacheFirst(OkHttpClient client) { super(client); } @Override public Response load(Uri uri, int networkPolicy) throws IOException { Response responseDiskCache = null; try { responseDiskCache = super.load(uri, 1 << 2); //NetworkPolicy.OFFLINE } catch (Exception ignored){} // ignore, handle null later if (responseDiskCache == null || responseDiskCache.getContentLength()<=0){ return super.load(uri, networkPolicy); //user normal policy } else { return responseDiskCache; } } } 

And in a singleton application in the OnCreate method, use it with picasso:

  OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setCache(new Cache(getCacheDir(), 100 * 1024 * 1024)); //100 MB cache, use Integer.MAX_VALUE if it is too low OkHttpDownloader downloader = new OkHttpDownloaderDiskCacheFirst(okHttpClient); Picasso.Builder builder = new Picasso.Builder(this); builder.downloader(downloader); Picasso built = builder.build(); Picasso.setSingletonInstance(built); 

3) Permissions required for defalut application cache folder

+6
Aug 31 '16 at 13:45
source share

I use this code and worked, perhaps useful for you:

 public static void makeImageRequest(final View parentView,final int id, final String imageUrl) { final int defaultImageResId = R.mipmap.user; final ImageView imageView = (ImageView) parentView.findViewById(id); Picasso.with(context) .load(imageUrl) .networkPolicy(NetworkPolicy.OFFLINE) .into(imageView, new Callback() { @Override public void onSuccess() { Log.v("Picasso","fetch image success in first time."); } @Override public void onError() { //Try again online if cache failed Log.v("Picasso","Could not fetch image in first time..."); Picasso.with(context).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE) .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE).error(defaultImageResId) .into(imageView, new Callback() { @Override public void onSuccess() { Log.v("Picasso","fetch image success in try again."); } @Override public void onError() { Log.v("Picasso","Could not fetch image again..."); } }); } }); } 
0
Nov 20 '16 at 21:37
source share

Add followning code to Application.onCreate , then use it normal

  Picasso picasso = new Picasso.Builder(context) .downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE)) .build(); picasso.setIndicatorsEnabled(true); picasso.setLoggingEnabled(true); Picasso.setSingletonInstance(picasso); 

If you cache images first, then do something like this in ProductImageDownloader.doBackground

 final Callback callback = new Callback() { @Override public void onSuccess() { downLatch.countDown(); updateProgress(); } @Override public void onError() { errorCount++; downLatch.countDown(); updateProgress(); } }; Picasso.with(context).load(Constants.imagesUrl+productModel.getGalleryImage()) .memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback); Picasso.with(context).load(Constants.imagesUrl+productModel.getLeftImage()) .memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback); Picasso.with(context).load(Constants.imagesUrl+productModel.getRightImage()) .memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback); try { downLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } if(errorCount == 0){ products.remove(productModel); productModel.isDownloaded = true; productsDatasource.updateElseInsert(productModel); }else { //error occurred while downloading images for this product //ignore error for now // FIXME: 9/27/2017 handle error products.remove(productModel); } errorCount = 0; downLatch = new CountDownLatch(3); if(!products.isEmpty() /*&& testCount++ < 30*/){ startDownloading(products.get(0)); }else { //all products with images are downloaded publishProgress(100); } 

and upload images as usual or using disk caching

  Picasso.with(this).load(Constants.imagesUrl+batterProduct.getGalleryImage()) .networkPolicy(NetworkPolicy.OFFLINE) .placeholder(R.drawable.GalleryDefaultImage) .error(R.drawable.GalleryDefaultImage) .into(viewGallery); 

Note:

Color

Red indicates that the image is selected from the network .

Color

Green indicates that the image is being retrieved from the cache .

Color

Blue indicates that the image is being ejected from disk .

Before releasing the application, uninstall or set it to false picasso.setLoggingEnabled(true); , picasso.setIndicatorsEnabled(true); if it is not required. Thankx

0
Sep 29 '17 at 8:18
source share

For the latest version 2.71828, this is your answer.

Q1 : Does it have no local disk cache?

A1 : Picasso has default caching and request flow like this

 App -> Memory -> Disk -> Server 

Wherever they first encounter their image, they will use that image and then stop the flow of requests. What about the response flow? Donโ€™t worry, here it is.

 Server -> Disk -> Memory -> App 

By default, they are first saved to the local drive for extended cache storage. Then memory, to use the cache instance.

You can use the built-in indicator in Picasso to see where the images are formed by turning this on.

 Picasso.get().setIndicatorEnabled(true); 

It will show a flag in the upper left corner of your photos.

  • A red flag means that images are coming from the server. (No caching on first boot)
  • A blue flag means that photos came from a local drive. (Caching)
  • A green flag means that images come from memory. (Instance Caching)

Q2 : How to enable caching on disk, since I will use the same image several times?

A2 : You do not need to turn it on. This is the default.

What you need to do is turn it off when you want your images to always be fresh. There are 2 ways to disable caching.

  1. Set .memoryPolicy() to NO_CACHE and / or NO_STORE, and the stream will look like this.

NO_CACHE will skip the search for images from memory.

 App -> Disk -> Server 

NO_STORE will skip storing images in memory the first time images are loaded.

 Server -> Disk -> App 
  1. Set .networkPolicy() to NO_CACHE and / or NO_STORE, and the stream will look like this.

NO_CACHE will skip the search for images from disk.

 App -> Memory -> Server 

NO_STORE will skip saving images to disk when loading images for the first time.

 Server -> Memory -> App 

You cannot disable a single one to not cache images completely. Here is an example.

 Picasso.get().load(imageUrl) .memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE) .networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE) .fit().into(banner); 

A stream completely without caching and storage will not look like this.

 App -> Server //Request Server -> App //Response 

Thus, you may need this to minimize the memory usage of your application.

Q3 : Do I need to add some disk permissions to the Android manifest file?

A3 : No, but do not forget to add the INTERNET permission for your HTTP request.

0
Jul 19. '19 at 14:51
source share

I had the same problem and used the Glide library. There is a cache out of the box. https://github.com/bumptech/glide

-2
May 05 '18 at 15:48
source share



All Articles