如何在毕加索中使用磁盘caching?
我正在使用毕加索在我的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); }
我已经启用debugging,它总是显示红色和绿色,但从不显示黄色
现在,如果我下次加载相同的图像和互联网不可用的图像不加载。
问题:
- 它没有本地磁盘caching吗?
- 我如何启用磁盘caching,因为我将多次使用相同的图像。
- 我需要添加一些磁盘权限到Android清单文件?
这就是我所做的。 效果很好
首先将OkHttp添加到app模块的gradle构build文件中
compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.squareup.okhttp:okhttp:2.4.0' compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
然后创build一个类扩展应用程序
import android.app.Application; import com.squareup.picasso.OkHttpDownloader; 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 OkHttpDownloader(this,Integer.MAX_VALUE)); Picasso built = builder.build(); built.setIndicatorsEnabled(true); built.setLoggingEnabled(true); Picasso.setSingletonInstance(built); } }
将其添加到清单文件如下所示:
<application android:name=".Global" .. > </application>
像平时一样使用毕加索。 没有变化。
编辑:
如果你只想使用caching的图像。 像这样调用库。 我注意到,如果我们不添加networkPolicy, 即使它们被caching , 图像也不会在完全离线的启动中显示出来 。 下面的代码解决了这个问题。
Picasso.with(this) .load(url) .networkPolicy(NetworkPolicy.OFFLINE) .into(imageView);
编辑#2
上面的代码的问题是,如果你清除caching,毕加索将继续在caching中查找它,并失败,下面的代码示例查看本地caching,如果没有发现离线,它将联机并补充caching。
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"); } }); } });
1)第一个问题的答案:根据Picasso Doc for With()方法
从()返回的全局默认Picasso实例会自动初始化,其默认值适用于大多数实现。
- LRU内存caching的15%是可用的应用程序RAM
- 2%存储空间的磁盘caching高达50MB但不低于5MB。
但全局默认毕加索的Disk Cache
操作仅适用于API 14+
2)回答第二个问题: Picasso
使用HTTP
客户端请求进行Disk Cache
操作所以你可以让你自己的http request header
有属性Cache-Control
用max-age
创build你自己的静态毕加索实例而不是默认的毕加索通过使用
1] HttpResponseCache (注意:仅适用于API 13+)
2] OkHttpClient (适用于所有的API)
使用OkHttpClient
创build您自己的Static Picasso类的示例 :
-
首先创build一个新的类来获得你自己的单身
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)回答第三个问题:磁盘Cache操作不需要任何磁盘权限
参考文献 : 关于磁盘caching的Github问题 ,已经通过@ jake-wharton回答了两个问题 – > 问题1和问题2
为了caching,我会使用OkHttp 拦截器来控制caching策略。 看看这个包含在OkHttp库中的示例。
下面是我将如何使用毕加索 –
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);
1)毕加索默认已经caching(详见ahmed hamdy answer)
2)如果你真的必须从磁盘caching,然后networking形象,我build议编写自己的下载:
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方法中的单身人士使用它与毕加索:
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应用程序caching文件夹不需要权限
我使用这个代码,工作,也许对你有用:
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..."); } }); } }); }
在Application.onCreate
添加followning代码,然后使用它正常
Picasso picasso = new Picasso.Builder(context) .downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE)) .build(); picasso.setIndicatorsEnabled(true); picasso.setLoggingEnabled(true); Picasso.setSingletonInstance(picasso);
如果你先caching图像,然后在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); }
并像正常或磁盘caching加载您的图像
Picasso.with(this).load(Constants.imagesUrl+batterProduct.getGalleryImage()) .networkPolicy(NetworkPolicy.OFFLINE) .placeholder(R.drawable.GalleryDefaultImage) .error(R.drawable.GalleryDefaultImage) .into(viewGallery);
注意:
红色表示图像是从networking获取的。
绿色表示图像是从高速缓冲存储器中取出的。
蓝色表示图像是从磁盘存储器中获取的。
在释放应用程序之前删除或设置它为false
picasso.setLoggingEnabled(true);
, picasso.setIndicatorsEnabled(true);
如果不是必需的。 Thankx