Come posso utilizzare la memorizzazione nella cache del disco in Picasso?

Sto usando Picasso per visualizzare l’immagine nella mia app 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); } 

Ho abilitato il debug e mostra sempre il rosso e il verde. Ma non mostra mai il giallo

Ora se carico la stessa immagine la volta successiva e internet non è disponibile, l’immagine non viene caricata.

Domande:

  1. Non ha cache del disco locale?
  2. Come posso abilitare la memorizzazione nella cache del disco poiché userò la stessa immagine più volte.
  3. Devo aggiungere qualche authorization sul disco al file manifest di Android?

Questo è quello che ho fatto. Funziona bene.

Innanzitutto aggiungi OkHttp al file gradle build del modulo dell’app:

 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' 

Quindi crea una class che estende l’ 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); } } 

aggiungilo al file Manifest come segue:

   

Ora usa Picasso come faresti normalmente. Nessun cambiamento.

MODIFICARE:

se si desidera utilizzare solo le immagini memorizzate nella cache. Chiama la biblioteca in questo modo. Ho notato che se non aggiungiamo la NetworkPolicy, le immagini non verranno visualizzate in un avvio completamente offline anche se sono memorizzate nella cache . Il codice qui sotto risolve il problema.

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

MODIFICA # 2

il problema con il codice precedente è che se si cancella la cache, Picasso continuerà a cercarlo offline nella cache e non riuscirà, il seguente esempio di codice esamina la cache locale, se non viene trovata offline, passa in linea e reintegra la 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"); } }); } }); 

1) risposta della prima domanda: secondo il metodo Picasso Doc per With ()

L’istanza globale predefinita di Picasso restituita da with () viene automaticamente inizializzata con valori predefiniti adatti alla maggior parte delle implementazioni.

  • Memoria cache LRU del 15% della RAM dell’applicazione disponibile
  • Cache del disco dello spazio di archiviazione 2% fino a 50 MB ma non inferiore a 5 MB.

Tuttavia, l’ operazione Disk Cache per il Picasso predefinito globale è disponibile solo su API 14+

2) risposta della seconda domanda: Picasso utilizza la richiesta del client HTTP per l’operazione Disk Cache Quindi è ansible rendere la propria http request header con proprietà Cache-Control con max-age E creare la propria istanza statica Picasso invece di Picasso predefinita Utilizzando

1] HttpResponseCache (Nota: funziona solo per API 13+)
2] OkHttpClient (funziona per tutte le API)

Esempio di utilizzo di OkHttpClient per creare la propria class Static Picasso:

  • Per prima cosa crea una nuova class per ottenere il tuo object picasso singleton

     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; } } 
  • usa il tuo object picasso singleton invece di Picasso.With()

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

3) rispondere alla terza domanda: non è necessario alcun permesso sul disco per le operazioni della cache del disco

Riferimenti : problema Github sulla cache del disco , due domande hanno ricevuto risposta da @ jake-wharton -> Question1 e Question2

Per la memorizzazione nella cache, utilizzare gli intercettatori di OkHttp per ottenere il controllo sulla politica di memorizzazione nella cache. Dai un’occhiata a questo esempio incluso nella libreria di OkHttp.

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

Ecco come lo userei con 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); 

1) Picasso di default ha cache (vedi ahmed hamdy answer)

2) Se davvero devi prendere un’immagine dalla cache del disco e poi dalla rete, ti consiglio di scrivere il tuo downloader personale:

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

E in Application singleton nel metodo OnCreate usalo con 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) Nessuna authorization necessaria per la cartella della cache dell'applicazione defalut

Io uso questo codice e ho lavorato, forse utile per te:

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

Aggiungi il codice di followering in Application.onCreate quindi usalo normalmente

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

Se prima immetti le immagini nella cache, fai qualcosa di simile 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); } 

e carica le tue immagini come normale o con la cache del disco

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

Nota:

Il colore rosso indica che l'immagine viene prelevata dalla rete .

Il colore verde indica che l'immagine viene recuperata dalla memoria cache .

Il colore blu indica che l'immagine viene recuperata dalla memoria del disco .

Prima di rilasciare l'app cancellare o impostarla come false picasso.setLoggingEnabled(true); , picasso.setIndicatorsEnabled(true); se non richiesto. thankx

Ho avuto lo stesso problema e ho usato invece la libreria Glide. Cache è fuori dalla scatola lì. https://github.com/bumptech/glide