J'essaie d'utiliser Retrofit & OKHttp pour mettre en cache les réponses HTTP. J'ai suivi l'essentiel et j'ai fini avec ce 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);
Et voici MyApi avec les en-têtes Cache-Control
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
);
Je demande d'abord en ligne et vérifie les fichiers de cache. La réponse et les en-têtes JSON corrects sont là. Mais lorsque j'essaie de demander hors ligne, je reçois toujours RetrofitError UnknownHostException
. Dois-je faire autre chose pour que Retrofit lise la réponse à partir du cache?
EDIT:
Puisque OKHttp 2.0.x HttpResponseCache
est Cache
, setResponseCache
estsetCache
Cache-Control: s-maxage=1209600, max-age=1209600
je ne sais pas si ça suffit.public
mot - clé devait être dans l'en-tête de réponse pour le faire fonctionner hors ligne. Mais ces en-têtes ne permettent pas à OkClient d'utiliser le réseau lorsqu'il est disponible. Est-il possible de définir une politique / stratégie de cache pour utiliser le réseau lorsqu'il est disponible?max-stale + max-age
est passé, il demande au réseau. Mais je veux définir max-stale une semaine. Cela permet de lire la réponse du cache même si un réseau est disponible.Réponses:
Modifier pour Retrofit 2.x:
OkHttp Interceptor est le bon moyen d'accéder au cache en mode hors connexion:
1) Créer un intercepteur:
2) Client d'installation:
3) Ajouter un client à la modernisation
Jetez également un coup @kosiara - Bartosz Kosarzycki de réponse . Vous devrez peut-être supprimer un en-tête de la réponse.
OKHttp 2.0.x (Vérifiez la réponse d'origine):
Puisque OKHttp 2.0.x
HttpResponseCache
estCache
,setResponseCache
estsetCache
. Vous devriez doncsetCache
aimer ceci:Réponse originale:
Il s'avère que la réponse du serveur doit être
Cache-Control: public
obligéeOkClient
de lire à partir du cache.De plus, si vous souhaitez faire une demande à partir du réseau lorsqu'il est disponible, vous devez ajouter un en-
Cache-Control: max-age=0
tête de demande. Cette réponse montre comment le faire paramétré. Voici comment je l'ai utilisé:la source
HttpResponseCache has been renamed to Cache.** Install it with OkHttpClient.setCache(...) instead of OkHttpClient.setResponseCache(...)
.if (Utils.isNetworkAvailable(context))
correct ou est-il censé être inversé ieif (!Utils.isNetworkAvailable(context))
?public okhttp3.Response intercept(Chain chain) throws IOException
n'est jamais appelé, il ne l'appelle que lorsque je suis en ligneToutes les réponses ci-dessus n'ont pas fonctionné pour moi. J'ai essayé d'implémenter le cache hors ligne dans la mise à niveau 2.0.0-beta2 . J'ai ajouté un intercepteur en utilisant la
okHttpClient.networkInterceptors()
méthode maisjava.net.UnknownHostException
je l'ai reçu lorsque j'ai essayé d'utiliser le cache hors ligne. Il s'est avéré que je devaisokHttpClient.interceptors()
aussi ajouter .Le problème était que le cache n'était pas écrit sur le stockage flash car le serveur est retourné,
Pragma:no-cache
ce qui empêche OkHttp de stocker la réponse. Le cache hors ligne ne fonctionnait pas même après la modification des valeurs d'en-tête de demande. Après quelques essais et erreurs, j'ai fait fonctionner le cache sans modifier le côté backend en supprimant pragma de la réponse au lieu de la requête -response.newBuilder().removeHeader("Pragma");
Rénovation: 2.0.0-beta2 ; OkHttp: 2.5.0
...
...
la source
interceptors ()
etnetworkInterceptors ()
est identique. Pourquoi avez-vous dupliqué cela?.networkInterceptors().add()
etinterceptors().add()
?Ma solution:
la source
La réponse est OUI, sur la base des réponses ci-dessus, j'ai commencé à écrire des tests unitaires pour vérifier tous les cas d'utilisation possibles:
J'ai construit une petite bibliothèque d'aide pour configurer facilement le cache OKHttp, vous pouvez voir l'unittest associé ici sur Github: https://github.com/ncornette/OkCacheControl/blob/master/okcache-control/src/test/java/com/ ncornette / cache / OkCacheControlTest.java
Unittest qui démontre l'utilisation du cache en mode hors connexion:
Comme vous pouvez le voir, le cache peut être utilisé même s'il a expiré. J'espère que cela aidera.
la source
en me basant sur la réponse de @ kosiara-bartosz-kasarzycki , j'ai créé un exemple de projet qui se charge correctement à partir de la mémoire-> disque-> réseau en utilisant retrofit, okhttp, rxjava et goyave. https://github.com/digitalbuddha/StoreDemo
la source
Cache avec Retrofit2 et OkHTTP3:
Méthode statique NetworkUtils.isNetworkAvailable ():
Ensuite, ajoutez simplement le client au constructeur de rénovation:
Source originale: https://newfivefour.com/android-retrofit2-okhttp3-cache-network-request-offline.html
la source