web-dev-qa-db-ja.com

OKHttpを使用したRetrofitがオフライン時にキャッシュデータを使用する方法

インターネットがないときにOkHttpでキャッシュを使用してレトロフィットしたい。

私は次のようにOkHttpClientを準備します:

    RestAdapter.Builder builder= new RestAdapter.Builder()
       .setRequestInterceptor(new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addHeader("Accept", "application/json;versions=1");
                if (MyApplicationUtils.isNetworkAvaliable(context)) {
                    int maxAge = 60; // read from cache for 1 minute
                    request.addHeader("Cache-Control", "public, max-age=" + maxAge);
                } else {
                    int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                    request.addHeader("Cache-Control", 
                        "public, only-if-cached, max-stale=" + maxStale);
                }
            }
    });

次のようにキャッシュを設定します。

   Cache cache = null;
    try {
        cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
    } catch (IOException e) {
        Log.e("OKHttp", "Could not create http cache", e);
    }

    OkHttpClient okHttpClient = new OkHttpClient();
    if (cache != null) {
        okHttpClient.setCache(cache);
    }

ルート権限を取得されたデバイスで、キャッシュディレクトリに「応答ヘッダー」とGzipファイルを含むファイルが保存されていることを確認しました。

しかし、GZipファイルには私の正解がコード化されていますが、オフラインのレトロフィットキャッシュから正解を取得できません。では、RetrofitにGZipファイルを読み取らせるにはどうすればよいでしょうか。また、どのファイルにする必要があるかを彼はどのように知ることができますか(他の応答を含むファイルがいくつかあるため)。

15
mac229

私の会社でも同様の問題があります:)

問題はサーバー側にありました。サーバーの応答で私は持っています:

_Pragma: no-cache
_

したがって、これを削除すると、すべてが機能し始めます。私がそれを削除する前に、私はいつもそのような例外を受け取ります:504 Unsatisfiable Request (only-if-cached)

さて、私の側の実装はどのように見えますか。

_    OkHttpClient okHttpClient = new OkHttpClient();

    File httpCacheDirectory = new File(appContext.getCacheDir(), "responses");

    Cache cache = new Cache(httpCacheDirectory, maxSizeInBytes);
    okHttpClient.setCache(cache);

    OkClient okClient = new OkClient(okHttpClient);

    RestAdapter.Builder builder = new RestAdapter.Builder();
    builder.setEndpoint(endpoint);
    builder.setClient(okClient);
_

どちら側が問題であるか(サーバーまたはアプリ)のテストで問題が発生した場合。このような機能を使用して、サーバーから受信したヘッダーを設定できます。

_private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
                               .removeHeader("Pragma")
                               .header("Cache-Control",
                                       String.format("max-age=%d", 60))
                               .build();
    }
};
_

単にそれを追加します:

_okHttpClient.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
_

ご覧のとおり、そのおかげで、テスト時に_Pragma: no-cache_ヘッダーを削除できました。

また、_Cache-Control_ヘッダーについて読むことをお勧めします。

max-agemax-stale

その他の便利なリンク:

HTTPヘッダーフィールドのリスト

キャッシュ制御

別のサンプルコード

25
Dawid Drozd