2017-01-18 55 views
11

Czy istnieje sposób na wykrycie, czy odpowiedź Retrofit pochodzi ze skonfigurowanej pamięci podręcznej OkHttp, czy jest odpowiedzią na żywo?Wykryj, czy odpowiedź OkHttp pochodzi z pamięci podręcznej (z funkcją Retrofit).

definicja

Klient:

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

definicja API

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

Przykład połączenie:

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

Odpowiedz

13

Za każdym razem mieć okhttp3.Response (retrofit2.Response.raw()), można sprawdzić, czy odpowiedź jest z pamięci podręcznej.

Cytując Jesse Wilson:

Istnieje kilka combosów.

.networkResponse()tylko - Twoja prośba została dostarczona z sieci wyłącznie.

.cacheResponse()tylko - Twoja prośba została dostarczona wyłącznie z pamięci podręcznej.

.networkResponse() i .cacheResponse() - Twoje żądanie było warunkowe GET, więc nagłówki pochodzą z sieci, a treść pochodzi z pamięci podręcznej.

Tak dla przykładu, metoda isFromCache wyglądałby następująco:

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

Czy ten cytat pochodzi z rozmowy lub z innego źródła online? Jeśli tak, czy mógłbyś podać link? – user2340612

+0

Właściwie lepiej jest sprawdzić 'result.response(). Raw(). CacheResponse()! = Null'. Jeśli klient ponownie sprawdzi buforowaną odpowiedź i otrzyma numer 304, zarówno 'networkResponse()' oraz 'cacheResponse()' będą miały wartość inną niż null. – apottere

+0

Tak, w zależności od semantyki i tego, jakie jest pożądane zachowanie aplikacji. –

8

Roztwór 1:

Za pomocą okhttp3.Response.cacheResponse() można sprawdzić, czy odpowiedź została odebrana z pamięci podręcznej:

Powoduje wyświetlenie nieprzetworzonej odpowiedzi otrzymanej z pamięci podręcznej. Będzie null, jeśli odpowiedź ta nie korzystać z pamięci podręcznej

Aby otrzymać surową odpowiedź OkHttp ze swojego modernizacji Response obect korzystania .raw(). tj .:

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

Rozwiązanie 2:

Możesz dodać Interceptor Klientowi OkHttp poprzez new OkHttpClient.Builder().addInterceptor(...). W tym Interceptorze pobierz odpowiedź przez chain.proceed(chain.request). Następnie użyj Response.cacheResponse() odpowiednio Response.networkResponse(), aby określić skąd pochodzi odpowiedź.

Pełny kod:

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

to zawsze oznacza, że ​​odpowiedź pochodzi z pamięci podręcznej! Nawet jeśli odinstaluję aplikację! – Fakher

+1

jej nie działa –

+1

zawsze wyświetla odpowiedź z pamięci podręcznej –

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

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

Ale chciałbym zaproponować Ci sprawdzić, czy networkResponse jest nieważna, ponieważ gdy żądanie jest buforowane i masz Odpowiedź networkResponse, przekazywana w dół strumień jest z sieci, a nie cache (w zależności od maxStale można określić w CacheControl). Sprawdź, czy networkResponse nie ma wartości null, jeśli null i twoja wartość cacheResponse nie jest pusta, odpowiedź jest wysyłana z pamięci podręcznej i na odwrót.