web-dev-qa-db-ja.com

OkHttp応答がキャッシュからのものかどうかを検出します(レトロフィットを使用)

レトロフィット応答が構成済みの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); // ???
});
17
whlk

_okhttp3.Response_retrofit2.Response.raw())がある場合はいつでも、応答がキャッシュからのものかどうかを確認できます。

ジェシー・ウィルソンを引用するには:

いくつかのコンボがあります。

。networkResponse()only–リクエストはネットワークからのみ提供されました。

。cacheResponse()only–リクエストはキャッシュから排他的に処理されました。

.networkResponse()および.cacheResponse()–リクエストは条件付きGETであったため、ヘッダーはネットワークからのものであり、本文はキャッシュからのものです。

したがって、例として、isFromCacheメソッドは次のようになります。

_boolean isFromCache(Result<?> result) {
  return result.response().raw().networkResponse() == null;
}
_
20
Eric Cochran

ソリューション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;
});
_
7
sebastian
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でない場合、応答はキャッシュから提供されます。

3
Omkar Amberkar

手遅れですが、多分これは誰かのために役立つでしょう。コンテンツがネットワークからのものである場合: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;
    }
});
2
kst

CacheResponseが存在する場合[〜#〜]および[〜#〜]networkResponse(存在する場合)の応答コードが304の場合、応答はキャッシュから送信されます。参照: https ://github.com/square/okhttp/issues/4539

0
Roman