如何在Picasso中使用磁盘缓存?

 肥羊羊和懒羊羊 发布于 2023-01-12 12:04

我正在使用Picasso在我的Android应用程序中显示图像:

/**
* 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);
}

我已启用调试,它始终显示红色和绿色.但从不显示黄色

现在,如果我下次加载相同的图像并且互联网不可用,则不会加载图像.

问题:

    它没有本地磁盘缓存吗?

    如何启用磁盘缓存,因为我将多次使用相同的图像.

    我需要为android清单文件添加一些磁盘权限吗?

Sanket Berde.. 226

这就是我做的.效果很好.

首先将OkHttp添加到app模块的gradle构建文件中:

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'

然后进行课程扩展 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);

    }
}

将它添加到Manifest文件,如下所示:




现在像往常一样使用毕加索.没有变化.

编辑:

如果您只想使用缓存图像.像这样调用库.我注意到,如果我们不添加networkPolicy,即使缓存它们,图像也不会在完全脱机启动时显示.下面的代码解决了这个问题.

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

编辑#2

上面代码的问题在于,如果清除缓存,Picasso将继续在缓存中脱机查找并失败,下面的代码示例查看本地缓存,如果未找到脱机,它将联机并补充缓存.

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");
            }
        });
    }
});

@SanketBerde:感谢快速注释,但我发现只有当应用程序在后台运行时(离线时),图像才会从内存中传出.如果我关闭应用程序,那么运行的应用程序很清楚,然后再次打开我的应用程序,图像不会从缓存中加载.我已设置即将出现的错误默认加载图像.这可能有什么问题? (4认同)

谢谢它的工作.为什么它不是公认的答案? (2认同)


ahmed hamdy.. 45

1)第一个问题的答案:根据Picasso Doc for With()方法

从with()返回的全局默认Picasso实例使用适合大多数实现的默认值自动初始化.

LRU内存缓存可用应用程序RAM的15%

2%存储空间的磁盘缓存高达50MB但不低于5MB.

Disk Cache全球默认毕加索的操作仅适用于API 14+

2)第二个问题的答案是:Picasso使用HTTP客户端请求Disk Cache的操作所以你可以使自己http request header拥有产权Cache-Controlmax-age 开创自己的静态毕加索实例,而不是默认的毕加索通过使用

1] HttpResponseCache(注意:仅适用于API 13+)
2] OkHttpClient(适用于所有API)

用于OkHttpClient创建自己的Static Picasso类的示例:

首先创建一个新类来获取自己的单例picasso对象

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

} 

使用你自己的单例picasso对象而不是Picasso.With()

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

3)回答第三个问题:磁盘缓存操作不需要任何磁盘权限

参考文献:关于磁盘缓存的Github问题,@ jake-wharton已经回答了两个问题- > 问题1和问题2

4 个回答
  • 这就是我做的.效果很好.

    首先将OkHttp添加到app模块的gradle构建文件中:

    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'
    

    然后进行课程扩展 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);
    
        }
    }
    

    将它添加到Manifest文件,如下所示:

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

    现在像往常一样使用毕加索.没有变化.

    编辑:

    如果您只想使用缓存图像.像这样调用库.我注意到,如果我们不添加networkPolicy,即使缓存它们,图像也不会在完全脱机启动时显示.下面的代码解决了这个问题.

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

    编辑#2

    上面代码的问题在于,如果清除缓存,Picasso将继续在缓存中脱机查找并失败,下面的代码示例查看本地缓存,如果未找到脱机,它将联机并补充缓存.

    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");
                }
            });
        }
    });
    

    2023-01-12 12:05 回答
  • 对于缓存,我会使用OkHttp 拦截器来控制缓存策略.查看OkHttp库中包含的此示例.

    https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/com/squareup/okhttp/recipes/RewriteResponseCacheControl.java

    以下是我与毕加索一起使用的方法 -

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

    2023-01-12 12:05 回答
  • 1)Picasso默认有缓存(见ahmed hamdy的答案)

    2)如果您真的必须从磁盘缓存然后网络中获取图像,我建议您编写自己的下载器:

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

    在应用程序单例中,OnCreate方法将它与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)defalut应用程序缓存文件夹不需要权限

    2023-01-12 12:05 回答
  • 1)第一个问题的答案:根据Picasso Doc for With()方法

    从with()返回的全局默认Picasso实例使用适合大多数实现的默认值自动初始化.

    LRU内存缓存可用应用程序RAM的15%

    2%存储空间的磁盘缓存高达50MB但不低于5MB.

    Disk Cache全球默认毕加索的操作仅适用于API 14+

    2)第二个问题的答案是:Picasso使用HTTP客户端请求Disk Cache的操作所以你可以使自己http request header拥有产权Cache-Controlmax-age 开创自己的静态毕加索实例,而不是默认的毕加索通过使用

    1] HttpResponseCache(注意:仅适用于API 13+)
    2] OkHttpClient(适用于所有API)

    用于OkHttpClient创建自己的Static Picasso类的示例:

    首先创建一个新类来获取自己的单例picasso对象

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

    使用你自己的单例picasso对象而不是Picasso.With()

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

    3)回答第三个问题:磁盘缓存操作不需要任何磁盘权限

    参考文献:关于磁盘缓存的Github问题,@ jake-wharton已经回答了两个问题- > 问题1和问题2

    2023-01-12 12:05 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有