it-swarm.com.de

Wie verwende ich Festplatten-Caching in Picasso?

Ich verwende Picasso, um ein Bild in meiner Android-App anzuzeigen:

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

Ich habe das Debuggen aktiviert und es wird immer entweder Rot oder Grün angezeigt

Wenn ich jetzt dasselbe Bild das nächste Mal lade und das Internet nicht verfügbar ist, wird das Bild nicht geladen.

Fragen:

  1. Hat es keinen lokalen Festplattencache?
  2. Wie kann ich das Festplatten-Caching aktivieren, da ich dasselbe Image mehrmals verwenden wird.
  3. Muss ich der Manifest-Datei von Android eine Festplattenberechtigung hinzufügen?
103
user93796

Das habe ich getan. Funktioniert gut.

Fügen Sie zunächst OkHttp zur Gradle-Build-Datei des App-Moduls hinzu: 

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'

Dann machen Sie eine Klasse, die Application erweitert.

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

    }
}

fügen Sie es wie folgt der Manifest-Datei hinzu:

<application
        Android:name=".Global"
        .. >

</application>

Verwenden Sie nun Picasso wie gewohnt. Keine Änderungen.

BEARBEITEN:

wenn Sie nur zwischengespeicherte Bilder verwenden möchten. Rufe die Bibliothek so auf. Ich habe festgestellt, dass Bilder nicht angezeigt werden, wenn wir die networkPolicy nicht hinzufügen bei einem vollständig offline-Start selbst wenn sie zwischengespeichert werden . Der folgende Code löst das Problem.

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

BEARBEITEN # 2

das Problem mit dem obigen Code besteht darin, dass Picasso nach dem Löschen des Cache im Cache weiterhin offline sucht und ausfällt. Im folgenden Codebeispiel wird der lokale Cache betrachtet. Wenn er nicht offline gefunden wird, geht er online und füllt den Cache neu.

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");
            }
        });
    }
});
211
Sanket Berde

1) Antwort auf die erste Frage: gemäß Picasso Doc für With () Methode

Die von with () zurückgegebene globale Picasso-Standardinstanz wird automatisch mit den Standardeinstellungen initialisiert, die für die meisten Implementierungen geeignet sind.

  • LRU-Speicher-Cache von 15% des verfügbaren Anwendungs-RAM
  • Festplatten-Cache mit 2% Speicherplatz bis zu 50 MB, jedoch nicht weniger als 5 MB.

Die Operation Disk Cache Für globales Standard-Picasso ist jedoch nur in API 14+ verfügbar

2) Antwort auf die zweite Frage: Picasso benutze die HTTP Client-Anfrage für die Disk Cache Operation Also können Sie Ihre eigene http request header - Eigenschaft Cache-Control Mit max-age Erstellen und Ihre eigene statische Picasso erstellen Instanz statt Standard Picasso Mit

1] HttpResponseCache (Hinweis: Funktioniert nur für API 13+)
2] OkHttpClient (Funktioniert für alle APIs)

Beispiel für die Verwendung von OkHttpClient zum Erstellen einer eigenen statischen Picasso-Klasse:

  • Erstellen Sie zunächst eine neue Klasse, um Ihr eigenes picasso Singleton-Objekt zu erhalten

    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;
        }
    
    } 
    
  • benutze dein eigenes singleton picasso Objekt anstelle von Picasso.With()

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

3) Antwort auf die dritte Frage: Sie benötigen keine Festplattenberechtigungen für Festplatten-Cache-Vorgänge

Verweise : Github-Problem mit dem Festplatten-Cache , zwei Fragen wurden von @ jake-wharton beantwortet -> Frage 1 und Frage 2

45
ahmed hamdy

Für das Caching würde ich OkHttp interceptors verwenden, um die Caching-Richtlinie zu kontrollieren. Schauen Sie sich dieses Beispiel an, das in der OkHttp-Bibliothek enthalten ist.

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

So würde ich es mit Picasso verwenden -

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);
21
Gaurav B

1) Picasso hat standardmäßig einen Cache-Speicher (siehe Antwort von ahmed hamdy).

2) Wenn Sie wirklich ein Image aus dem Festplattencache nehmen und dann das Netzwerk verwenden müssen, empfehle ich Ihnen, Ihren eigenen Downloader zu schreiben:

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

    }
}

Und in Application Singleton in der Methode OnCreate verwenden Sie es mit 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) Keine Berechtigungen für den Cache-Ordner der Anwendung defalut erforderlich

6
tsm

Für die aktuellste Version 2.71828 Dies sind Ihre Antworten.

Q1: Hat es keinen lokalen Festplatten-Cache?

A1: Es gibt ein Standard-Caching in Picasso und der Anforderungsfluss ist genau so

App -> Memory -> Disk -> Server

Wo immer sie ihr Image zuerst trafen, verwenden sie dieses Image und stoppen dann den Anforderungsfluss. Was ist mit dem Antwortfluss? Mach dir keine Sorgen, hier ist es.

Server -> Disk -> Memory -> App

Standardmäßig werden sie zuerst auf einem lokalen Datenträger für den erweiterten Aufbewahrungscache gespeichert. Dann der Speicher für die Instanznutzung des Caches.

Sie können die integrierte Anzeige in Picasso verwenden, um zu sehen, wo sich Bilder bilden, indem Sie diese aktivieren.

Picasso.get().setIndicatorEnabled(true);

Es zeigt eine Flagge in der oberen linken Ecke Ihrer Bilder.

  • Rot Flag bedeutet, dass die Bilder vom Server stammen. (Kein Caching beim ersten Laden)
  • Bla Flag bedeutet, dass die Fotos von der lokalen Festplatte stammen. (Caching)
  • Grün Flag bedeutet, dass die Bilder aus dem Speicher stammen. (Instanz-Caching)

Q2: Wie aktiviere ich das Disk-Caching, da ich dasselbe Image mehrmals verwenden werde?

A2: Sie müssen es nicht aktivieren. Dies ist die Standardeinstellung.

Was Sie tun müssen, ist DEAKTIVIEREN es, wenn Sie Ihre Bilder immer frisch wollen. Es gibt zwei Möglichkeiten zum Zwischenspeichern von Inhalten.

  1. Setzen Sie .memoryPolicy() auf NO_CACHE und/oder NO_STORE und Flow wird so aussehen.

NO_CACHE überspringt das Nachschlagen von Bildern aus dem Speicher.

App -> Disk -> Server

NO_STORE überspringt das Speichern von Bildern im Speicher, wenn die ersten Bilder geladen werden.

Server -> Disk -> App
  1. Setzen Sie .networkPolicy() auf NO_CACHE und/oder NO_STORE und Flow wird so aussehen.

NO_CACHE überspringt das Nachschlagen von Bildern von der Festplatte.

App -> Memory -> Server

NO_STORE überspringt das Speichern von Bildern auf der Festplatte, wenn die ersten Bilder geladen werden.

Server -> Memory -> App

Sie können DEAKTIVIEREN weder für vollständig keine Bilder zwischenspeichern. Hier ist ein Beispiel.

Picasso.get().load(imageUrl)
             .memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE)
             .networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
             .fit().into(banner);

Der Ablauf ohne Caching und ohne Speichern sieht folgendermaßen aus.

App -> Server //Request

Server -> App //Response

Dies ist möglicherweise erforderlich, um die Speichernutzung Ihrer App zu minimieren.

Q: Muss ich der Manifest-Datei Android eine Festplattenberechtigung hinzufügen?

A: Nein, aber vergessen Sie nicht, die INTERNET-Berechtigung für Ihre HTTP-Anfrage hinzuzufügen.

1

Ich benutze diesen Code und habe gearbeitet, vielleicht nützlich für Sie:

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

                            });
                }
            });

}
0
Iman Marashi

Fügen Sie folgenden Code in Application.onCreate hinzu, und verwenden Sie ihn normal

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

Wenn Sie zuerst Bilder zwischenspeichern, machen Sie etwas 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);
        }

und laden Sie Ihre Bilder wie gewohnt oder mit Datenträger-Zwischenspeicherung

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

Hinweis: 

Rot Farbe zeigt an, dass das Bild von Netzwerk abgerufen wird.

Grün Farbe zeigt an, dass das Bild aus Cache-Speicher abgerufen wird.

Blau Farbe zeigt an, dass das Bild vom Plattenspeicher abgerufen wird .

Bevor Sie die App freigeben, löschen oder setzen Sie sie falsepicasso.setLoggingEnabled(true);, picasso.setIndicatorsEnabled(true);, falls nicht erforderlich. Vielen Dank

0
Qamar