1

Retrofit と OkHttp を使用してキャッシュを実装しようとしています。ここで私がすでに行ったこと:

private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {

        @Override public Response intercept(Interceptor.Chain chain) throws IOException {
            Request originalRequest = chain.request();
            Request.Builder request = originalRequest.newBuilder();
            Response response = chain.proceed(request.build());
            return response.newBuilder()
                    .removeHeader("Pragma")
                    .removeHeader("Cache-Control")
                    .header("Cache-Control", "max-age=2419200")
                    .build();
        }
    };

    @Provides
    @Singleton
    OkHttpClient provideHttpClient(Context context) {


        File httpCacheDirectory = new File(context.getCacheDir(), "responses");
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        Cache cache = new Cache(httpCacheDirectory, cacheSize);


        HttpLoggingInterceptor oggingInterceptor = new HttpLoggingInterceptor();
        oggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return new OkHttpClient.Builder()
                .cache(cache)
                .connectTimeout(3, TimeUnit.SECONDS)
                .writeTimeout(3, TimeUnit.SECONDS)
                .readTimeout(3, TimeUnit.SECONDS)
                .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
                .addInterceptor(oggingInterceptor).build();
    }

次に、このインターセプターを HTTP クライアントに追加します。

.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)

応答ディレクトリ内にファイルがありますが、インターネットに接続せずにコンテンツを読み込もうとすると、次のエラーが表示されます。

ホスト「example.com」を解決できません: ホスト名に関連付けられたアドレスがありません

http 応答をどこかに保存し、インターネット接続がない場合にロードしたいだけです。

インターネット接続があれば、キャッシュを書き換えたい。

4

2 に答える 2

4

私はあなたと同じ問題に遭遇しました、今私は記事を見つけて私の問題を解決します、それはあなたを助けることができると思います.

get cache の時間が経過したため、okhttp はキャッシュを空にしてサーバーを再度要求しますが、キャッシュが空になったため、エラー Exception が送信されます。

Interceptor でいくつかのリクエスト設定を行うことができます。

CacheControl.Builder cacheBuilder = new CacheControl.Builder();
            cacheBuilder.maxAge(0, TimeUnit.SECONDS);
            cacheBuilder.maxStale(365,TimeUnit.DAYS);
            CacheControl cacheControl = cacheBuilder.build();

            Request request = chain.request();
            if(!StateUtils.isNetworkAvailable(MyApp.mContext)){
                request = request.newBuilder()
                        .cacheControl(cacheControl)
                        .build();
            }

maxAge : キャッシュの最大有効期間を制御します

maxStale : キャッシュを制御する Out of date time

完全なコード:

weiBoApiRetrofit() {

        File httpCacheDirectory = new File(MyApp.mContext.getCacheDir(), "responses");
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        Cache cache = new Cache(httpCacheDirectory, cacheSize);

        OkHttpClient client = new OkHttpClient.Builder()
                .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
                .cache(cache).build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        WeiBoApiService = retrofit.create(WeiBoApi.class);
    }

    //cache
    Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {

            CacheControl.Builder cacheBuilder = new CacheControl.Builder();
            cacheBuilder.maxAge(0, TimeUnit.SECONDS);
            cacheBuilder.maxStale(365,TimeUnit.DAYS);
            CacheControl cacheControl = cacheBuilder.build();

            Request request = chain.request();
            if(StateUtils.isNetworkAvailable(MyApp.mContext)){
                request = request.newBuilder()
                        .cacheControl(cacheControl)
                        .build();
            }
            Response originalResponse = chain.proceed(request);
            if (StateUtils.isNetworkAvailable(MyApp.mContext)) {
                int maxAge = 60  * 60; // read from cache
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, max-age=" + maxAge)
                        .build();
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }
        }
    };
}

私は私の問題を解決することができます。

しかし、Interceptor Useless の Response でヘッダーを設定する理由がわかりませんでした。「 Interceptor は、これら 2 つの要求と応答を設定する必要があります」と言う人もいます。

お役に立てれば幸いです。

于 2016-07-28T06:29:56.840 に答える