レトロフィット応答が構成済みのOkHttpキャッシュからのものか、それともライブ応答かを検出する方法はありますか?
クライアント定義:
Cache cache = new Cache(getCacheDirectory(context), 1024 * 1024 * 10);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(cache)
.build();
APIの定義:
@GET("/object")
Observable<Result<SomeObject>> getSomeObject();
呼び出し例:
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); // ???
});
_okhttp3.Response
_ (retrofit2.Response.raw()
)がある場合はいつでも、応答がキャッシュからのものかどうかを確認できます。
ジェシー・ウィルソンを引用するには:
いくつかのコンボがあります。
。networkResponse()only–リクエストはネットワークからのみ提供されました。
。cacheResponse()only–リクエストはキャッシュから排他的に処理されました。
.networkResponse()および.cacheResponse()–リクエストは条件付きGETであったため、ヘッダーはネットワークからのものであり、本文はキャッシュからのものです。
したがって、例として、isFromCache
メソッドは次のようになります。
_boolean isFromCache(Result<?> result) {
return result.response().raw().networkResponse() == null;
}
_
ソリューション1:
okhttp3.Response.cacheResponse() を使用すると、キャッシュから応答が受信されたかどうかを確認できます。
キャッシュから受け取った生の応答を返します。この応答がキャッシュを使用しなかった場合はnullになります
レトロフィット応答オブジェクトから生のOkHttp応答を取得するには、.raw()
を使用します。例:
_public boolean isFromCache(Result<?> retroResult) {
return retroResult.response().raw().cacheResponse() != null;
}
_
ソリューション2:
インターセプターをnew OkHttpClient.Builder().addInterceptor(...)
を介してOkHttpクライアントに追加できます。このインターセプターでは、chain.proceed(chain.request)
を介して応答を取得します。次に、Response.cacheResponse()
をそれぞれ使用してResponse.networkResponse()
を返し、応答がどこから来たかを判別します。
完全なコード:
_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;
});
_
if (response.raw().cacheResponse() != null) {
// true: response was served from cache
}
if (response.raw().networkResponse() != null) {
// true: response was served from network/server
}
しかし、リクエストがキャッシュされてnetworkResponseが渡されると、ストリームに渡される応答はネットワークではなくキャッシュからのものであるため、networkResponseがnullかどうかを確認することをお勧めします(CacheControlで指定したmaxStaleによって異なります)。 。したがって、networkResponseがnullでないかどうかを確認します。nullでcacheResponseがnullでない場合、応答はキャッシュから提供されます。
手遅れですが、多分これは誰かのために役立つでしょう。コンテンツがネットワークからのものである場合:response.networkResponse()
およびresponse.cacheResponse()
はnullではなく、コンテンツがキャッシュからのものである場合response.networkResponse()
はnullなので、@ sebastianからのコード:
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;
});
このコードで置き換えるだけです:
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.addInterceptor(new Interceptor() {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
if (response.networkResponse() != null) {
Log.v(TAG, "Response from networkResponse(): " + response.networkResponse());
} else if (response.cacheResponse() != null) {
Log.v(TAG, "Response from cacheControl(): " + response.cacheResponse());
}
return response;
}
});
CacheResponseが存在する場合[〜#〜]および[〜#〜]networkResponse(存在する場合)の応答コードが304の場合、応答はキャッシュから送信されます。参照: https ://github.com/square/okhttp/issues/4539