Question

Je charge une image depuis le disque en utilisant Picasso, par exemple., Picasso.with(ctx).load(new File("/path/to/image")).into(imageView), mais chaque fois que j'enregistre une nouvelle image dans ce fichier et que j'actualise mon ImageView, Picasso a toujours le bitmap en cache.

Est-il possible d'invalider le cache dans Picasso ?

Était-ce utile?

La solution

Dans les versions récentes de Picasso, il existe une nouvelle méthode d'invalidation, sans aucune solution de contournement, donc je pense que la classe PicassoTools personnalisée mentionnée précédemment est désormais obsolète dans ce cas.

Picasso.with(getActivity()).invalidate(file);

Autres conseils

En fait, d'après votre propre réponse, il existe un moyen plus simple de le faire sans bifurquer la bibliothèque.Ajoutez cette classe au package com.squareup.picasso.

package com.squareup.picasso;

public class PicassoTools {

    public static void clearCache (Picasso p) {
        p.cache.clear();
    }
}

Étant donné que le cache a une visibilité sur les packages, cette classe util peut vider le cache pour vous.Il suffit de l'appeler :

PicassoTools.clearCache(Picasso.with(context));

Abandonnez la vérification du cache mémoire et du cache disque en indiquant la politique de mémoire par indicateur :emoryPolicy.NO_CACHE et NetworkPolicy.NO_CACHE comme extrait de code ci-dessous :

   mPicasso.with(mContext)
            .load(url)
            .memoryPolicy(MemoryPolicy.NO_CACHE )
            .networkPolicy(NetworkPolicy.NO_CACHE)
            .resize(512, 512)
            .error(R.drawable.login)
            .noFade()
            .into(imageView);

Essayez d'utiliser:

Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)

Une autre option consiste à supprimer le répertoire de cache lui-même, par exemple au démarrage de l'application :

deleteDirectoryTree(context.getCacheDir());

où:

/**
 * Deletes a directory tree recursively.
 */
public static void deleteDirectoryTree(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory()) {
        for (File child : fileOrDirectory.listFiles()) {
            deleteDirectoryTree(child);
        }
    }

    fileOrDirectory.delete();
}

Cela supprime tout le répertoire de cache, ce qui est très bien si vous souhaitez simuler la première utilisation de votre application.Si vous souhaitez uniquement supprimer le cache Picasso, ajoutez "picasso-cache" au chemin.

Ce que vous pouvez faire si vous souhaitez supprimer tout le cache en même temps, c'est créer un fichier personnalisé Picasso.LruCache, puis utilisez le clear méthode dessus.

Voici un exemple :

Picasso.Builder builder = new Picasso.Builder(this);
LruCache picassoCache = new LruCache(this);
builder.memoryCache(picassoCache);
Picasso.setSingletonInstance(builder.build());

Pour vider le cache :

picassoCache.clear();

L’ordre de recherche d’image dans Picasso est :Cache mémoire -> Cache disque -> Réseau

Il existe donc quelques scénarios dans lesquels nous devons invalider le cache dans Picasso :

1.Invalider le cache mémoire :

  • Cas d'utilisation :Lorsque l'image est déjà mise à jour dans le cache disque ou sur l'hôte distant
  • Solution:Vider le cache de l'URL, du fichier, de l'Uri s'il existe

    mPicasso.with(appContext).invalidate(File);
    mPicasso.with(appContext).invalidate(Url);
    mPicasso.with(appContext).invalidate(Uri);
    

.

2. Invalider le cache mémoire et le cache disque En ligne

※note: En ligne signifie mettre à jour directement vers ImageView

  • Cas utilisateur :Image mise à jour sur l'hôte distant

  • Solution:Abandonner l'image sur le cache mémoire et le cache disque, puis demander l'image sur l'hôte distant

    mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE )
        .networkPolicy(NetworkPolicy.NO_CACHE)
        .into(imageView);
    

    -> Abandonner le cache mémoire et le cache disque

.

3. Invalider le cache mémoire et le cache disque Hors ligne

※ note: Hors ligne signifie que la mise à jour n'est pas mise à jour vers ImageView, il suffit de récupérer l'arrière-plan pour l'utiliser plus tard

  • Cas utilisateur :Vous savez que l'image sur l'hôte distant a été mise à jour, mais vous souhaitez uniquement mettre à jour le cache uniquement pour l'utiliser ultérieurement (pas de mise à jour dans la vue image)
  • Solution:récupérer seulement

     mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE)
        .networkPolicy(NetworkPolicy.NO_CACHE)
        .fetch();
    

※Note:Utiliser fetch() est une bonne chose mais cela consomme également des ressources réseau, alors réfléchissez bien, vérifiez le scénario 4 ci-dessous pour une meilleure solution

4. Invalider le cache mémoire et le cache disque Hors ligne si le cache disque existe

  • Cas utilisateur :Invalider le cache uniquement s'il existe déjà dans le cache disque
  • Solution:Devrait vérifier le disque en utilisant le paramètre :Cache NetworkPolicy.OFFLINE avant la récupération

     mPicasso.with(appContext)
        .load(url)
        .memoryPolicy(MemoryPolicy.NO_CACHE)
        .networkPolicy(NetworkPolicy.OFFLINE)
        .fetch(new Callback() {
            @Override
            public void onSuccess() {
                //Success: mean disk cache exist -> should do actual fetch
                picasso.load(url).fetch();
            }
    
            @Override
            public void onError() {
            //Failed: mean disk cache not exist
        }
    });
    

Picasso est une bibliothèque incroyable, j'espère que Squareup ajoutera une API plus pratique pour gérer le cache dans un avenir proche.

Vous pouvez vider le cache d'images de Picasso en définissant votre propre cache et en l'effaçant.Ce code a été testé sur Picasso 2.5.0

private Picasso picasso;
private LruCache picassoLruCache;

picassoLruCache = new LruCache(context);

// Set cache
picasso = new Picasso.Builder(context) //
        .memoryCache(picassoLruCache) //
        .build();

// Clear cache
picassoLruCache.clear();

La boucle n'est pas jolie, mais cette approche a résolu mon problème avec le cache et Picasso.Utilisez-le uniquement lorsque vous souhaitez invalider le cache pour une URL spécifique. Cette approche est lente et n'est probablement pas la bonne façon de procéder mais fonctionne pour moi.

    String url = "http://www.blablabla.com/Raiders.jpg";
    Picasso.with(this).invalidate(url);
    Picasso.with(this)
            .load(url)
            .networkPolicy(
                    NetworkUtils.isConnected(this) ?
                            NetworkPolicy.NO_CACHE : NetworkPolicy.OFFLINE)
            .resize(200, 200)
            .centerCrop()
            .placeholder(R.mipmap.ic_avatar)
            .error(R.mipmap.ic_avatar)
            .into(imageView);

Une partie très importante manque dans la réponse acceptée ici.J'ai trouvé l'astuce ici : http://blogs.candoerz.com/question/124660/android-image-cache-is-not-clearing-in-picasso.aspx

Le simple fait d'appeler la ligne suivante ne viderait pas le cache d'une photo lorsque vous utilisez des options personnalisées telles que le redimensionnement, le recadrage central, etc. lors de l'affichage de l'image originale.

Picasso.with(getContext()).invalidate(file);

La solution:

Lors de l'affichage de l'image, utilisez stableKey() méthode.

Picasso.with(getContext()).load(new File(fileUri))
                         .skipMemoryCache()
                         .placeholder(R.drawable.placeholder)
                         .stableKey(fileUri)
                         .into(imageview);

Ensuite, vous pourrez vider le cache de ce fichier ultérieurement en appelant ceci :

Picasso.with(getContext()).invalidate(fileUri);

J'espère que cela aidera.

Vous pouvez ignorer le cache mémoire en skipMemoryCache()

voir ce qui suit

        Picasso.with(this)
            .load(IMAGE_URL)
            .skipMemoryCache()
            .placeholder(R.drawable.placeholder)
            .error(R.drawable.no_image)
            .into(mImageViewPicasso);

diplôme compile "com.squareup.picasso:picasso:2.4.0"

Une autre option consiste à enregistrer la nouvelle image dans un fichier différent de l'original.Étant donné que le cache bitmap Picasso est séparé du chemin du fichier, le chargement de la nouvelle image à partir d'un fichier différent entraînera un échec du cache.Cela présente également l’avantage de ne pas avoir à vider tout le cache.

utiliser shutdown() à la place selon le code source;l'arrêt cessera d'accepter d'autres demandes et effacera tout le cache

 /** Stops this instance from accepting further requests. */
  public void shutdown() {
    if (this == singleton) {
      throw new UnsupportedOperationException("Default singleton instance cannot be shutdown.");
    }
    if (shutdown) {
      return;
    }
    cache.clear();
    cleanupThread.shutdown();
    stats.shutdown();
    dispatcher.shutdown();
    for (DeferredRequestCreator deferredRequestCreator : targetToDeferredRequestCreator.values()) {
      deferredRequestCreator.cancel();
    }
    targetToDeferredRequestCreator.clear();
    shutdown = true;
  }

De plus, vous ne pouvez pas arrêter l'instance singleton.Vous devez donc avoir une variable d'instance pour Picasso.N'oubliez pas de réinitialiser l'instance Picasso à chaque fois que vous shutdown() le afin de le réutiliser

File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top