2017-01-18 1 views
11

Y at-il un moyen de détecter si une réponse Retrofit provient du cache OkHttp configuré ou est une réponse en direct?Détecter si la réponse OkHttp provient du cache (avec Retrofit)

définition du client:

Cache cache = new Cache(getCacheDirectory(context), 1024 * 1024 * 10); 
OkHttpClient okHttpClient = new OkHttpClient.Builder() 
      .cache(cache) 
      .build(); 

définition Api:

@GET("/object") 
Observable<Result<SomeObject>> getSomeObject(); 

appel Exemple:

RetroApi retroApi = new Retrofit.Builder() 
      .client(okHttpClient) 
      .baseUrl(baseUrl) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build() 
      .create(RetroApi.class); 

result = retroApi.getSomeObject().subscribe((Result<SomeObject> someObjectResult) -> { 
    isFromCache(someObjectResult); // ??? 
}); 

Répondre

13

Chaque fois que vous avez un okhttp3.Response (retrofit2.Response.raw()), vous pouvez vérifier si la réponse est à partir du cache.

Pour citer Jesse Wilson:

Il y a quelques combos.

.networkResponse()seulement - votre demande a été fournie exclusivement par le réseau.

.cacheResponse()seulement - votre requête a été servie exclusivement à partir du cache. .networkResponse() et .cacheResponse() - votre requête était un GET conditionnel, donc les en-têtes proviennent du réseau et le corps provient du cache.

Donc, pour votre exemple, la méthode isFromCache ressemblerait à ceci:

boolean isFromCache(Result<?> result) { 
    return result.response().raw().networkResponse() == null; 
} 
+0

Est-ce que cette citation provient d'une conférence ou d'une autre ressource en ligne? Si oui, pourriez-vous s'il vous plaît fournir un lien? – user2340612

+0

Il est préférable de vérifier 'result.response(). Raw(). CacheResponse()! = Null'. Si le client valide à nouveau la réponse mise en cache et reçoit un 304, à la fois 'networkResponse()' et 'cacheResponse()' seront non-null. – apottere

+0

Oui, en fonction de la sémantique et du comportement de votre application. –

8

Solution 1:

En utilisant le okhttp3.Response.cacheResponse() vous pouvez vérifier si la réponse a été reçue du cache:

Renvoie la réponse brute reçue du cache. Sera nul si cette réponse n'a pas utilisé le cache

Pour obtenir la réponse OkHttp brute de votre réponse de mise à niveau obect utiliser .raw(). i.e. .:

public boolean isFromCache(Result<?> retroResult) { 
    return retroResult.response().raw().cacheResponse() != null; 
} 

Solution 2:

Vous pouvez ajouter un intercepteur au Client OkHttp via new OkHttpClient.Builder().addInterceptor(...). Dans cet intercepteur récupérer la réponse via chain.proceed(chain.request). Ensuite, utilisez Response.cacheResponse() respectivement Response.networkResponse() pour déterminer l'origine de la réponse.

code complet:

new OkHttpClient.Builder().addInterceptor(chain -> { 
     Response response = chain.proceed(chain.request()); 
     if (response.cacheControl() != null) { 
      // from cache 
     } else if (response.networkResponse() != null) { 
      // from network 
     } 
     return response; 
}); 
+2

cela signifie toujours que la réponse provient du cache! Même si je désinstalle l'application! – Fakher

+1

ne fonctionne pas –

+1

La réponse est toujours celle du cache –

1
if (response.raw().cacheResponse() != null) { 
    // true: response was served from cache 
} 

if (response.raw().networkResponse() != null) { 
    // true: response was served from network/server 
} 

Mais je vous suggère de vérifier si votre networkResponse est nulle, car une fois que la demande est mis en cache et vous avez une réponse réseau aussi, votre réponse transmise dans le flux provient du réseau et non du cache (en fonction du paramètre maxStale que vous avez spécifié sur CacheControl). Vérifiez donc si networkResponse n'est pas nul, si null et votre cacheResponse n'est pas nul, la réponse est servie du cache réciproquement.