Cache in Picasso ungültig machen

76

Ich lade ein Bild mit Picasso von der Festplatte , z. B. Picasso.with(ctx).load(new File("/path/to/image")).into(imageView)aber wenn ich ein neues Bild in dieser Datei speichere und mein Bild aktualisiere ImageView, hat Picasso immer noch die Bitmap zwischengespeichert.

Ist es möglich, den Cache in Picasso ungültig zu machen?

Maarten
quelle
1
Nach Picasso.with(getActivity()).invalidate(file);wie kann ich wieder zwischenspeichern?
Smoking-Welt

Antworten:

86

In den neueren Versionen von Picasso gibt es eine neue Methode zum Ungültigmachen ohne Problemumgehungen. Daher denke ich, dass die zuvor erwähnte benutzerdefinierte PicassoTools-Klasse in diesem Fall veraltet ist

Picasso.with(getActivity()).invalidate(file);
mes
quelle
3
Nun, das macht eine einzelne Datei ungültig. Es gibt immer noch keine Methode, um den gesamten Cache ungültig zu machen. Wie auch immer, ich habe vor fast einem Jahr darauf geantwortet, daher bin ich nicht überrascht, dass sie es seitdem hinzugefügt haben.
Shalafi
Ja, es macht eine einzelne Datei ungültig, wie der Autor wollte. Es ist nicht erforderlich, den gesamten Cache zu leeren. Es ist nicht effektiv. Haben Sie vor einem Jahr versucht, es selbst in Picasso zu implementieren?
Mes
Stellen Sie sicher, dass Sie die neueste Version von Picasso verwenden IllegalStateException. github.com/square/picasso/commit/…
Jared Rummler
8
Invalidate
8
Sie müssen das Bild mit laden, Picasso.with(imageView.getContext()).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);da invalidate () den Netzwerkcache nicht löscht
Joe Maher
82

Basierend auf Ihrer eigenen Antwort gibt es einen einfacheren Weg, dies zu tun, ohne die Bibliothek zu verzweigen. Fügen Sie diese Klasse dem Paket com.squareup.picasso hinzu.

package com.squareup.picasso;

public class PicassoTools {

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

Da der Cache Paketsichtbarkeit hat, kann diese util-Klasse den Cache für Sie leeren. Sie müssen es nur nennen:

PicassoTools.clearCache(Picasso.with(context));
Shalafi
quelle
21
Sie müssen nicht auf das Glas zugreifen. Sie müssen diese Datei erstellen und in das richtige Paket (com.squareup.picasso)
legen
4
Gibt es eine Möglichkeit, dies zu tun, wenn Sie Gradle mit Android Studio anstelle der Add-On-JAR-Datei verwenden?
TheLettuceMaster
3
Nein, Sie müssen das Picasso-Glas nicht berühren, sondern nur die Datei im richtigen Paket erstellen.
Shalafi
7
Schade, dass Picasso.with(getApplication()).cache.clear();das nicht funktioniert. Es wäre viel sauberer.
Michael Schmidt
3
Das Feld Picasso.cache ist nicht sichtbar !!
Iman Marashi
66

Brechen Sie die Überprüfung des Speichercaches und des Festplattencaches ab, indem Sie die Speicherrichtlinie anhand des Flags angeben: emoryPolicy.NO_CACHE und NetworkPolicy.NO_CACHE wie folgt: Codefragment:

   mPicasso.with(mContext)
            .load(url)
            .memoryPolicy(MemoryPolicy.NO_CACHE )
            .networkPolicy(NetworkPolicy.NO_CACHE)
            .resize(512, 512)
            .error(R.drawable.login)
            .noFade()
            .into(imageView);
Виталий Ермолович
quelle
1
Vielen Dank! Das Hinzufügen von .networkPolicy (NetworkPolicy.NO_CACHE) hat bei mir funktioniert.
Kann Uludağ
1
Durch diese Antwort werden Bilder nie zwischengespeichert! Warum also?
Iman Marashi
9
@ImanMarashi Es ist nützlich, wenn Sie normalerweise mit derselben URL und einem anderen Bildwert arbeiten (Beispiel: amazonws.com/yourProject/user_profile_images/user1/profile.jpg. Die URL ändert sich nie, ihr Wert jedoch.
Borja
14

Versuchen zu benutzen:

Picasso.with(ctx).load(new File("/path/to/image")).skipMemoryCache().into(imageView)
user3361741
quelle
Dies funktioniert, aber ich möchte, dass das Bild das Bild im Cache speichert , nur nicht daraus liest, wenn wir wissen, dass das Bild veraltet ist! Ich habe herausgefunden, dass dies in Picasso nicht so ist, wie es ist, also werde ich Ihre Antwort als richtig markieren.
Maarten
Ich wollte irgendwie ein Bild aktualisieren, das zuvor geladen wurde. skipMemoryCache () hat es geschafft! Vielen Dank!
Russellhoff
Dies ist jetzt veraltet
Rob
12

Wenn Sie den gesamten Cache auf einmal löschen möchten, können Sie eine benutzerdefinierte Datei erstellen Picasso.LruCacheund anschließend die clearMethode verwenden.

Hier ist ein Beispiel:

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

So leeren Sie den Cache:

picassoCache.clear();
Aerilys
quelle
Gleiche Empfehlung von Picasso lib: github.com/square/picasso/issues/935
vmeyer
12

Die Reihenfolge der Suchbilder in Picasso lautet: Speichercache -> Festplattencache -> Netzwerk

Es gibt also nur wenige Szenarien, in denen der Cache in Picasso ungültig gemacht werden muss:

1. Ungültigen Speichercache:

  • Usercase: Wenn das Image bereits im Festplatten-Cache oder auf dem Remote-Host aktualisiert wurde
  • Lösung: Löschen Sie den Cache von URL, Datei und Uri, falls vorhanden

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

.

2. Ungültiger Speichercache und Festplattencache online

※ Hinweis: Online- Mittelaktualisierung direkt auf ImageView

  • Benutzerfall: Image auf Remote-Host aktualisiert

  • Lösung: Brechen Sie das Image im Speicher- und Festplatten-Cache ab und fordern Sie das Image auf dem Remote-Host an

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

    -> Speicher- und Festplatten-Cache abbrechen

.

3. Ungültigen Speicher-Cache und Festplatten-Cache offline

※ Hinweis: Offline bedeutet Update nicht auf ImageView aktualisieren, sondern nur Hintergrundabruf zur späteren Verwendung

  • Benutzerfall: Sie wissen, dass das Image auf dem Remote-Host aktualisiert wurde, möchten den Cache jedoch nur für die spätere Verwendung aktualisieren (nicht in die Image-Ansicht aktualisieren).
  • Lösung: Nur abrufen

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

※ Hinweis: Die Verwendung von fetch () ist gut, verbraucht aber auch Netzwerkressourcen. Überlegen Sie daher sorgfältig, ob Sie Szenario 4 unten auf eine bessere Lösung überprüfen

4. Ungültigen Speichercache und Festplattencache Offline, wenn Festplattencache vorhanden ist

  • Benutzerfall: Cache nur ungültig machen, wenn er bereits im Festplatten-Cache vorhanden ist
  • Lösung: Sollte die Festplatte vor dem Abrufen mit dem Parameter: NetworkPolicy.OFFLINE-Cache überprüfen

     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 ist eine erstaunliche Bibliothek. Ich hoffe, Squareup wird in der kommenden Zukunft mehr Komfort-API für die Verwaltung des Cache hinzufügen.

NguyenDat
quelle
11

Eine andere Möglichkeit besteht darin, das Cache-Verzeichnis selbst zu löschen, beispielsweise beim Start der App:

deleteDirectoryTree(context.getCacheDir());

wo:

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

    fileOrDirectory.delete();
}

Dadurch wird das gesamte Cache-Verzeichnis gelöscht. Dies ist in Ordnung, wenn Sie die erste Verwendung Ihrer App simulieren möchten. Wenn Sie nur den Picasso-Cache löschen möchten, fügen Sie dem Pfad "Picasso-Cache" hinzu.

Lawrence Kesteloot
quelle
@ Lawrence Kesteloot könntest du mir bei dieser Frage helfen? stackoverflow.com/questions/33657619/… . Ich habe Ihre Methode bereits mit großem Erfolg angewendet, aber ich habe jetzt Probleme. Vielen Dank im Voraus
madsongr
1
Andere Antworten entfernen nur den Speicher-Cache, aber nicht den Disc-Cache - dies kümmert sich auch um die Disc! :)
Mohit Singh
8

Sie können den Bildcache von Picasso löschen, indem Sie Ihren eigenen Cache festlegen und diesen löschen. Dieser Code wurde auf Picasso 2.5.0 getestet

private Picasso picasso;
private LruCache picassoLruCache;

picassoLruCache = new LruCache(context);

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

// Clear cache
picassoLruCache.clear();
Stanley Kou
quelle
6

Schleife nicht schön, aber dieser Ansatz hat mein Problem mit Cache und Picasso behoben. Verwenden Sie diese Option nur, wenn Sie den Cache für eine bestimmte URL ungültig machen möchten. Dieser Ansatz ist langsam und wahrscheinlich nicht die richtige Vorgehensweise, funktioniert aber für mich.

    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);
João Machete
quelle
2

Ein sehr wichtiger Teil fehlt in der hier akzeptierten Antwort. Ich habe den Trick von hier gefunden: http://blogs.candoerz.com/question/124660/android-image-cache-is-not-clearing-in-picasso.aspx

Wenn Sie nur die folgende Zeile aufrufen, wird der Cache eines Fotos nicht gelöscht, wenn Sie beim Anzeigen des Originalbilds benutzerdefinierte Optionen wie Größenänderung, Zuschneiden in der Mitte usw. verwenden.

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

Die Lösung:

Verwenden Sie beim Anzeigen des Bildes die stableKey()Methode.

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

Anschließend können Sie den Cache dieser Datei später löschen, indem Sie Folgendes aufrufen:

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

Hoffe das wird helfen.

Orangenbaum
quelle
1

Sie können den Speichercache überspringen skipMemoryCache()

siehe folgendes

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

gradle compile "com.squareup.picasso:picasso:2.4.0"

Android Dev
quelle
0

Eine andere Möglichkeit besteht darin, das neue Bild in einer anderen Datei als das Original zu speichern. Da der Picasso-Bitmap-Cache vom Dateipfad getrennt ist, führt das Laden des neuen Bildes aus einer anderen Datei zu einem Cache-Fehler. Dies hat auch den Nebeneffekt, dass nicht der gesamte Cache geleert werden muss.

Ilan Klinghofer
quelle
0

Verwenden Sie shutdown()stattdessen gemäß Quellcode. Durch das Herunterfahren werden keine weiteren Anforderungen mehr akzeptiert und der gesamte Cache geleert

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

Außerdem können Sie die Singleton-Instanz nicht herunterfahren. Sie benötigen also eine Instanzvariable für Picasso. Vergessen Sie nicht, die Picasso-Instanz jedes Mal neu zu initialisieren, shutdown()um sie wiederzuverwenden

Amol Desai
quelle
0
File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));
JoeSpin
quelle