Ich versuche, Retrofit & OKHttp zum Zwischenspeichern von HTTP-Antworten zu verwenden. Ich folgte diesem Kern und endete mit diesem Code:
File httpCacheDirectory = new File(context.getCacheDir(), "responses");
HttpResponseCache httpResponseCache = null;
try {
httpResponseCache = new HttpResponseCache(httpCacheDirectory, 10 * 1024 * 1024);
} catch (IOException e) {
Log.e("Retrofit", "Could not create http cache", e);
}
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setResponseCache(httpResponseCache);
api = new RestAdapter.Builder()
.setEndpoint(API_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(okHttpClient))
.build()
.create(MyApi.class);
Und das ist MyApi mit den Cache-Control-Headern
public interface MyApi {
@Headers("Cache-Control: public, max-age=640000, s-maxage=640000 , max-stale=2419200")
@GET("/api/v1/person/1/")
void requestPerson(
Callback<Person> callback
);
Zuerst fordere ich online an und überprüfe die Cache-Dateien. Die richtige JSON-Antwort und die richtigen Header sind vorhanden. Aber wenn ich versuche, offline anzufordern, bekomme ich immer RetrofitError UnknownHostException
. Gibt es noch etwas, das ich tun sollte, damit Retrofit die Antwort aus dem Cache liest?
EDIT:
Da OKHttp 2.0.x HttpResponseCache
ist Cache
, setResponseCache
istsetCache
Cache-Control: s-maxage=1209600, max-age=1209600
Ich weiß nicht , ob es genug ist.public
Schlüsselwort im Antwortheader enthalten sein musste, damit es offline funktioniert. Mit diesen Headern kann OkClient das Netzwerk jedoch nicht verwenden, wenn es verfügbar ist. Gibt es überhaupt eine Möglichkeit, die Cache-Richtlinie / -Strategie für die Verwendung des Netzwerks festzulegen, wenn diese verfügbar ist?max-stale + max-age
übergeben, wird vom Netzwerk angefordert. Aber ich möchte maximal eine Woche alt werden. Dadurch wird die Antwort aus dem Cache gelesen, auch wenn ein Netzwerk verfügbar ist.Antworten:
Für Nachrüstung bearbeiten 2.x:
OkHttp Interceptor ist der richtige Weg, um offline auf den Cache zuzugreifen:
1) Interceptor erstellen:
2) Setup-Client:
3) Client zur Nachrüstung hinzufügen
Prüfen Sie auch @kosiara - Bartosz Kosarzycki ‚s Antwort . Möglicherweise müssen Sie einen Header aus der Antwort entfernen.
OKHttp 2.0.x (Überprüfen Sie die ursprüngliche Antwort):
Da OKHttp 2.0.x
HttpResponseCache
istCache
,setResponseCache
istsetCache
. Das sollte dir alsosetCache
gefallen:Ursprüngliche Antwort:
Es stellt sich heraus, dass die Serverantwort erfolgen muss
Cache-Control: public
, umOkClient
aus dem Cache zu lesen.Wenn Sie eine Anforderung aus dem Netzwerk anfordern möchten, sollten Sie den
Cache-Control: max-age=0
Anforderungsheader hinzufügen . Diese Antwort zeigt, wie es parametrisiert wird. So habe ich es benutzt:quelle
HttpResponseCache has been renamed to Cache.** Install it with OkHttpClient.setCache(...) instead of OkHttpClient.setResponseCache(...)
.if (Utils.isNetworkAvailable(context))
richtig oder soll es umgekehrt sein dhif (!Utils.isNetworkAvailable(context))
?public okhttp3.Response intercept(Chain chain) throws IOException
wird es nie angerufen, es wird nur angerufen, wenn ich online binAlle oben genannten Antworten haben bei mir nicht funktioniert. Ich habe versucht, den Offline-Cache in Retrofit 2.0.0-Beta2 zu implementieren . Ich habe einen Interceptor mit der
okHttpClient.networkInterceptors()
Methode hinzugefügt , aber erhalten,java.net.UnknownHostException
als ich versucht habe, den Cache offline zu verwenden. Es stellte sich heraus, dass ich auch hinzufügen mussteokHttpClient.interceptors()
.Das Problem war, dass der Cache nicht in den Flash-Speicher geschrieben wurde, da der Server zurückgegeben wurde,
Pragma:no-cache
wodurch verhindert wurde, dass OkHttp die Antwort speichert. Der Offline-Cache funktionierte auch nach dem Ändern der Anforderungsheaderwerte nicht. Nach einigem Ausprobieren funktionierte der Cache, ohne die Backend-Seite zu ändern, indem Pragma anstelle der Anforderung aus der Antwort entfernt wurde.response.newBuilder().removeHeader("Pragma");
Nachrüstung: 2.0.0-beta2 ; OkHttp: 2.5.0
...
...
quelle
interceptors ()
undnetworkInterceptors ()
ist identisch. Warum hast du das dupliziert?Meine Lösung:
quelle
Die Antwort lautet JA. Basierend auf den obigen Antworten habe ich begonnen, Komponententests zu schreiben, um alle möglichen Anwendungsfälle zu überprüfen:
Ich habe eine kleine Hilfsbibliothek erstellt, um den OKHttp-Cache einfach zu konfigurieren. Sie können die entsprechenden Unittest hier auf Github sehen: https://github.com/ncornette/OkCacheControl/blob/master/okcache-control/src/test/java/com/ ncornette / cache / OkCacheControlTest.java
Unittest, das die Verwendung des Caches im Offline-Modus demonstriert:
Wie Sie sehen, kann der Cache auch dann verwendet werden, wenn er abgelaufen ist. Hoffe es wird helfen.
quelle
Aufbauend auf der Antwort von @ kosiara-bartosz-kasarzycki habe ich ein Beispielprojekt erstellt, das mithilfe von Retrofit, Okhttp, Rxjava und Guave ordnungsgemäß aus dem Speicher-> Festplatten-> Netzwerk geladen wird. https://github.com/digitalbuddha/StoreDemo
quelle
Cache mit Retrofit2 und OkHTTP3:
Statische Methode von NetworkUtils.isNetworkAvailable ():
Fügen Sie dann einfach einen Client zum Retrofit Builder hinzu:
Ursprüngliche Quelle: https://newfivefour.com/android-retrofit2-okhttp3-cache-network-request-offline.html
quelle