将 Square Picasso 的缓存大小限制为最大 60MB

Posted

技术标签:

【中文标题】将 Square Picasso 的缓存大小限制为最大 60MB【英文标题】:Limiting Square Picasso's cache size to 60MB max 【发布时间】:2016-07-12 06:56:50 【问题描述】:

我目前正在使用 Picasso 在我的应用程序中的多个回收站视图中下载和缓存图像。到目前为止,毕加索已经使用了大约 49MB 的缓存大小,我担心随着更多图像的使用,这会变得更高。

我正在使用默认的 Picasso.with(context) 对象。请回答以下问题:

1) 有没有办法限制毕加索缓存的大小。 MemoryPolicy 和 NetworkPolicy 设置为 NO_CACHE 不是一个选项。我需要缓存,但要达到一定水平(最大 60MB)

2) 毕加索有没有办法像 Glide DiskCacheStrategy.RESULT 那样存储调整大小/裁剪的图像

3) 如果选择使用 OKHTTP,请指导我使用它来限制 Picasso 的缓存大小的好教程。 (毕加索 2.5.2)

4) 由于我使用的是 Picasso 的 Gradle 依赖项,如何添加清晰的缓存功能,如下所示:

Clear Cache memory of Picasso

【问题讨论】:

【参考方案1】:

请试试这个,它似乎对我很有用:

我将它用作单例。 只需将 60 放在 DISK/CACHE 大小参数所在的位置即可。

//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;
    

【讨论】:

所以现在我在设置中看到的缓存是内存缓存还是磁盘缓存或两者兼而有之?如果我决定不使用 OKHTTP,毕加索还会超过 60mb 吗? 在调用 getSharedInstance() 后我必须调用:Picasso.setSingletonInstance(picasso) 吗?? 如果您选择不使用 OkHttp,您仍然可以只使用 memoryCache。至于调用它应该是这样的: picasso = PicassoSingleton.getSharedInstance(this);然后是: picasso.load("")).into(""); 对不起,你的答案很好,但如果我没记错的话,它在 picasso 2.5 之后不再有效。方法 setCache 等...已被弃用,将不起作用。无论如何,感谢你引导我找到我需要的东西:)【参考方案2】:

1) 是的,很简单:new com.squareup.picasso.LruCache(60 * 1024 * 1024)。 (只需在您的 Picasso 实例中使用您的 Cache 实例,例如 new Picasso.Builder(application).memoryCache(cache).build()

2) Picasso 自动使用 resize() 和其他方法的参数作为内存缓存键的一部分。至于磁盘缓存,不,毕加索不会触及您的磁盘缓存。磁盘缓存由 HTTP 客户端(如 OkHttp)负责。

3) 如果您在谈论磁盘缓存大小:new OkHttpClient.Builder().cache(new Cache(directory, maxSize)).build()。 (现在你有类似new Picasso.Builder(application).memoryCache(cache).downloader(new OkHttp3Downloader(client)).build()

4) Picasso 的 Cache 接口有一个clear() 方法(当然LruCache 实现了它)。

【讨论】:

【参考方案3】:

好的,我在 Picasso 内部做了很多挖掘工作,OKHTTP 的内部正在努力找出缓存是如何发生的,策略是什么等等。

对于尝试使用最新的 picasso 2.5+ 和 Okhttp 3+ 的人,接受的答案将不起作用! (我不检查最新的不好:()

1) getSharedInstance 不是线程安全的,使其同步。

2) 如果您不每次都进行此调用,请拨打Picasso.setSingletonInstance(thecustompicassocreatedbygetsharedinstance)

附注在 try 块内执行此操作,以避免在静态单例未销毁的破坏后非常快速地重新打开活动时出现非法状态异常。还要确保在任何 Picasso.with(context) 调用之前调用此方法

3) 查看代码,我建议人们不要干预 LruCache,除非绝对确定,否则很容易导致浪费未使用的 RAM 或设置低->内存不足异常。

4) 如果你甚至不做任何这些都很好。默认情况下,毕加索会尝试从其内置的 okhttpdownloader 中创建磁盘缓存。但这可能会也可能不会根据您使用的毕加索版本而起作用。如果它不起作用,它会使用默认的 java URL 下载器,该下载器也会自己进行一些缓存。

5) 我看到做这一切的唯一主要原因是获得清除缓存功能。众所周知,毕加索不会轻易做到这一点,因为它在包装内受到保护。而且像我这样的大多数普通人都使用 gradle 来包含使我们无法访问缓存清除权限的包。

这是代码以及我想要的所有选项。这将使用 jakewharton 的 Picasso 2.5.2、Okhttp 3.4.0 和 OkHttp3Downloader。

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;



【讨论】:

以上是关于将 Square Picasso 的缓存大小限制为最大 60MB的主要内容,如果未能解决你的问题,请参考以下文章

Picasso

使用Picasso进行网络图片的加载

转载一行代码加载网络图片到ImageView——Android Picasso

picasso-强大的Android图片下载缓存库

Picasso源码解析

Picasso源码解析