Comment utiliser la mise en cache de disque dans Picasso?

J’utilise Picasso pour afficher l’image dans mon application 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); } 

J’ai permis le débogage et il affiche toujours soit rouge et vert .Mais ne montre jamais jaune

Maintenant, si je charge la même image la prochaine fois et que l’Internet n’est pas disponible, l’image n’est pas chargée.

Des questions:

  1. N’a-t-il pas de cache de disque local?
  2. Comment puis-je activer la mise en cache du disque car j’utiliserai plusieurs fois la même image.
  3. Dois-je append une autorisation de disque au fichier manifeste Android?

C’est ce que j’ai fait. Fonctionne bien.

Ajoutez d’abord l’OkHttp au fichier de construction graduel du module d’application:

 comstack 'com.squareup.picasso:picasso:2.5.2' comstack 'com.squareup.okhttp3:okhttp:3.10.0' comstack 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' 

Ensuite, créez une Application étend la classe

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

ajoutez-le au fichier manifeste comme suit:

   

Utilisez maintenant Picasso comme vous le feriez normalement. Aucun changement.

MODIFIER:

si vous souhaitez utiliser uniquement les images en cache Appelez la bibliothèque comme ceci. J’ai remarqué que si nous n’ajoutons pas le paramètre networkPolicy, les images ne s’afficheront pas dans un démarrage complètement déconnecté, même si elles sont mises en cache . Le code ci-dessous résout le problème.

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

EDIT # 2

Le problème avec le code ci-dessus est que si vous effacez le cache, Picasso continuera à le rechercher hors ligne dans le cache et échouera. L’exemple de code suivant examine le cache local.

 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) réponse à la première question: selon Picasso Doc pour la méthode With ()

L’instance Picasso par défaut globale renvoyée par with () est automatiquement initialisée avec des valeurs par défaut adaptées à la plupart des implémentations.

  • Cache mémoire LRU de 15% de la mémoire vive disponible de l’application
  • Cache disque de 2% d’espace de stockage jusqu’à 50 Mo mais pas moins de 5 Mo.

Mais l’ opération de Disk Cache pour Picasso par défaut global n’est disponible que sur API 14+

2) réponse de la deuxième question: Picasso utilise la HTTP client HTTP pour une opération de Disk Cache Vous pouvez ainsi créer votre propre en- http request header Cache-Control avec max-age et créer votre propre instance de Picasso statique au lieu de Picasso par défaut.

1] HttpResponseCache (Remarque: Fonctionne uniquement pour l’API 13+)
2] OkHttpClient (Fonctionne pour toutes les API)

Exemple d’utilisation d’ OkHttpClient pour créer votre propre classe OkHttpClient Picasso:

  • Créez d’abord une nouvelle classe pour obtenir votre propre object singleton 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; } } 
  • utilisez votre propre object singleton picasso Au lieu de Picasso.With()

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

3) réponse à la troisième question: vous n’avez pas besoin d’permissions de disque pour les opérations de cache disque

Références : Deux questions ont été résolues par @ jake-wharton -> Question1 et Question2

Pour la mise en cache, j’utiliserais les intercepteurs OkHttp pour prendre le contrôle de la politique de mise en cache. Découvrez cet exemple inclus dans la bibliothèque OkHttp.

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

Voici comment je l’utilise avec 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 a par défaut le cache (voir la réponse de ahmed hamdy)

2) Si vous devez vraiment prendre une image du cache disque puis du réseau, je vous recommande d’écrire votre propre téléchargeur:

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

Et dans Application singleton dans la méthode OnCreate, utilisez-la avec 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) Pas d'permissions nécessaires pour le dossier de cache des applications par défaut

J’utilise ce code et j’ai travaillé, peut-être utile pour vous:

 public static void makeImageRequest(final View parentView,final int id, final Ssortingng 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..."); } }); } }); } 

Ajouter le code suivant dans Application.onCreate puis l’utiliser normalement

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

Si vous cachez des images en premier, faites ceci dans 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); } 

et chargez vos images comme d'habitude ou avec la mise en cache du disque

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

Remarque:

La couleur rouge indique que l'image est extraite du réseau .

La couleur verte indique que l'image est extraite de la mémoire cache .

La couleur bleue indique que l'image est extraite de la mémoire du disque .

Avant de libérer l'application, supprimez-la ou définissez-la false picasso.setLoggingEnabled(true); , picasso.setIndicatorsEnabled(true); si non requirejs Thankx

J’ai eu le même problème et j’ai utilisé la bibliothèque Glide à la place. Le cache est hors de la liste. https://github.com/bumptech/glide