3

I am currently using Picasso to download and cache images in my app inside multiple recycler views. So far Picasso has used around 49MB cache size and i am worried that as more images come into play, this will become much higher.

I am using the default Picasso.with(context) object. Please answer the following:

1) Is there a way to restrict the Size of Picasso's cache. MemoryPolicy and NetworkPolicy set to NO_CACHE isn't an option. I need caching but upto a certain level (60MB max)

2) Is there a way in picasso to store Resized/cropped images like in Glide DiskCacheStrategy.RESULT

3) If the option is to use OKHTTP, please guide me to a good tutorial for using it to limit Picasso's cache size. (Picasso 2.5.2)

4) Since i am using a Gradle dependency of Picasso, how can i add a clear Cache function as shown here:

Clear Cache memory of Picasso

Community
  • 1
  • 1
Kushan
  • 5,855
  • 3
  • 31
  • 45

3 Answers3

3

Please try this one, it does seem to work great for me:

I use it as a Singleton. Just put 60 where DISK/CACHE size parameters are.

//Singleton Class for Picasso Downloading, Caching and Displaying Images Library
public class PicassoSingleton {

    private static Picasso mInstance;
    private static long mDiskCacheSize = CommonConsts.DISK_CACHE_SIZE * 1024 * 1024; //Disk Cache
    private static int mMemoryCacheSize = CommonConsts.MEMORY_CACHE_SIZE * 1024 * 1024; //Memory Cache
    private static OkHttpClient mOkHttpClient; //OK Http Client for downloading
    private static Cache diskCache;
    private static LruCache lruCache;


    public static Picasso getSharedInstance(Context context) {
        if (mInstance == null && context != null) {
            //Create disk cache folder if does not exist
            File cache = new File(context.getApplicationContext().getCacheDir(), "picasso_cache");
            if (!cache.exists())
                cache.mkdirs();

            diskCache = new Cache(cache, mDiskCacheSize);
            lruCache = new LruCache(mMemoryCacheSize);
            //Create OK Http Client with retry enabled, timeout and disk cache
            mOkHttpClient = new OkHttpClient();
            mOkHttpClient.setConnectTimeout(CommonConsts.SECONDS_TO_OK_HTTP_TIME_OUT, TimeUnit.SECONDS);
            mOkHttpClient.setRetryOnConnectionFailure(true);
            mOkHttpClient.setCache(diskCache);

            //For better performence in Memory use set memoryCache(Cache.NONE) in this builder (If needed)
            mInstance = new Picasso.Builder(context).memoryCache(lruCache).
                            downloader(new OkHttpDownloader(mOkHttpClient)).
                            indicatorsEnabled(CommonConsts.SHOW_PICASSO_INDICATORS).build();

        }
    }
        return mInstance;
}

    public static void updatePicassoInstance() {
        mInstance = null;
    }

    public static void clearCache() {
        if(lruCache != null) {
            lruCache.clear();
        }
        try {
            if(diskCache != null) {
                diskCache.evictAll();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        lruCache = null;
        diskCache = null;
    }
}
Gilad Eshkoli
  • 1,253
  • 11
  • 27
  • so right now what i see in the settings as cache, is it the memory cache or is it a disk cache or both? Also will picasso ever go above 60mb should i decide to not use OKHTTP? – Kushan Jul 12 '16 at 07:26
  • will i have to call : Picasso.setSingletonInstance(picasso) after calling getSharedInstance() ?? – Kushan Jul 12 '16 at 07:33
  • You will still be able to use only the memoryCache should you opt-out using OkHttp. As for calling it should be like this: picasso = PicassoSingleton.getSharedInstance(this); and afterwards this: picasso.load("")).into(""); – Gilad Eshkoli Jul 12 '16 at 08:10
  • 2
    Sorry bud, yours is a good answer, but it no longer works after picasso 2.5 if i'm not wrong. The methods setCache etc... have been deprecated off and will not work. Anyway Kudos to you for guiding me to what i needed :) – Kushan Jul 12 '16 at 21:33
2

1) Yeah, easy: new com.squareup.picasso.LruCache(60 * 1024 * 1024). (just use your Cache instance in your Picasso instance like new Picasso.Builder(application).memoryCache(cache).build())

2) Picasso automatically uses the resize() and other methods' parameters as part of the keys for the memory cache. As for the disk cache, nope, Picasso does not touch your disk cache. The disk cache is the responsibility of the HTTP client (like OkHttp).

3) If you are talking about disk cache size: new OkHttpClient.Builder().cache(new Cache(directory, maxSize)).build(). (now you have something like new Picasso.Builder(application).memoryCache(cache).downloader(new OkHttp3Downloader(client)).build())

4) Picasso's Cache interface has a clear() method (and LruCache implements it, of course).

Eric Cochran
  • 8,414
  • 5
  • 50
  • 91
1

Ok, I did a lot of digging inside Picasso, and OKHTTP's internal working to find out how caching happens, whats the policy etc.

For people trying to use latest picasso 2.5+ and Okhttp 3+, the accepted answer WILL NOT WORK!! (My bad for not checking with the latest :( )

1) The getSharedInstance was not Thread safe, made it synchronized.

2) If you don't to do this calling everytime, do a Picasso.setSingletonInstance(thecustompicassocreatedbygetsharedinstance)

P.S. do this inside a try block so as to avoid illegalstateexception on activity reopening very quickly after a destroy that the static singleton is not destroyed. Also make sure this method gets called before any Picasso.with(context) calls

3) Looking at the code, I would advise people not to meddle with LruCache unless absolutely sure, It can very easily lead to either waste of unused RAM or if set low-> Outofmemoryexceptions.

4)It is fine if you don't even do any of this. Picasso by default tries to make a disk cache from it's inbuilt okhttpdownloader. But this might or might not work based on what picasso version you use. If it doesn't work, it uses default java URL downloader which also does some caching of its own.

5) Only main reason i see to do all this is to get the Clear Cache functionality. As we all know Picasso does not give this easily as it is protected inside the package. And most mere mortals like me use gradle to include the package leaving us out in the dust to not have cache clearing access.

Here is the code along with all the options for what i wanted. This will use Picasso 2.5.2 , Okhttp 3.4.0 and OkHttp3Downloader by jakewharton.

package com.example.project.recommendedapp;


import android.content.Context;
import android.util.Log;

import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.LruCache;
import com.squareup.picasso.Picasso;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.OkHttpClient;

//Singleton Class for Picasso Downloading, Caching and Displaying Images Library
public class PicassoSingleton {

private static Picasso mInstance;
private static long mDiskCacheSize = 50*1024*1024; //Disk Cache limit 50mb

//private static int mMemoryCacheSize = 50*1024*1024; //Memory Cache 50mb, not currently using this. Using default implementation

private static OkHttpClient mOkHttp3Client; //OK Http Client for downloading
private static OkHttp3Downloader okHttp3Downloader;
private static Cache diskCache;
private static LruCache lruCache;//not using it currently


public static synchronized Picasso getSharedInstance(Context context)
{
    if(mInstance == null) {
        if (context != null) {
            //Create disk cache folder if does not exist
            File cache = new File(context.getApplicationContext().getCacheDir(), "picasso_cache");
            if (!cache.exists()) {
                cache.mkdirs();
            }

            diskCache = new Cache(cache, mDiskCacheSize);
            //lruCache = new LruCache(mMemoryCacheSize);//not going to be using it, using default memory cache currently
            lruCache = new LruCache(context); // This is the default lrucache for picasso-> calculates and sets memory cache by itself

            //Create OK Http Client with retry enabled, timeout and disk cache
            mOkHttp3Client = new OkHttpClient.Builder().cache(diskCache).connectTimeout(6000, TimeUnit.SECONDS).build();  //100 min cache timeout



            //For better performence in Memory use set memoryCache(Cache.NONE) in this builder (If needed)
            mInstance = new Picasso.Builder(context).memoryCache(lruCache).downloader(new OkHttp3Downloader(mOkHttp3Client)).indicatorsEnabled(true).build();

        }
    }
    return mInstance;
}

public static void deletePicassoInstance()
{
    mInstance = null;
}

public static void clearLRUCache()
{
    if(lruCache!=null) {
        lruCache.clear();
        Log.d("FragmentCreate","clearing LRU cache");
    }

    lruCache = null;

}

public static void clearDiskCache(){
    try {
        if(diskCache!=null) {
            diskCache.evictAll();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    diskCache = null;

}
}
Kushan
  • 5,855
  • 3
  • 31
  • 45