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?


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

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

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

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)

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

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.


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

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

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.


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"


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.


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


0
File f = new File(path, name);
Picasso.with(this).invalidate(Uri.fromFile(f));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.