, Для меня фокус заключался в использовании обоих этих перехватчиков. Надеюсь, это поможет вам.

прочитал много вопросов и ответов по моей проблеме, но я не могу понять, как ее решить.

Мне нужно получить ответ от сервера и сохранить его в кеше. После этого, когда устройство находится в автономном режиме, я хочу использовать кэшированный ответ. Когда устройство подключено к сети, я хочу получить ответ именно с сервера.

Выглядит не так сложно.

Вот способ (примеры кода) я пытаюсь сделать это:

1) Способ создания кеша

Cache provideOkHttpCache() {
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        Cache cache = new Cache(this.getCacheDir(), cacheSize);
        return cache;
    }

2) Создать перехватчик для изменения заголовков управления кэшем

 Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
        @Override
        public okhttp3.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 (isOnline()) {
                request = request.newBuilder()
                        .cacheControl(cacheControl)
                        .build();
            }
            okhttp3.Response originalResponse = chain.proceed(request);
            if (isOnline()) {
                int maxAge = 20; // read from cache
                okhttp3.Response response = originalResponse.newBuilder()
                        .header("cache-control", "public, max-age=" + maxAge)
                        .build();
                return response;
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                okhttp3.Response response = originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
                return response;
            }
        }
    };

3) Создать OkHttpClient и модифицировать

OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addInterceptor(httpLoggingInterceptor)
            .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
            .cache(provideOkHttpCache())
            .build();

    retrofit = new Retrofit.Builder()
            .client(okHttpClient)
            .baseUrl("https://randomuser.me/")
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

4) Способ совершить сетевой вызов

private void networkCall() {
    Log.v(TAG, "networkCall() is called");
    Call<RandomUsers> randomUsersCall = getRandomUserService().getRandomUsers(10);
    randomUsersCall.enqueue(new Callback<RandomUsers>() {
        @Override
        public void onResponse(Call<RandomUsers> call, @NonNull Response<RandomUsers> response) {
            if (response.isSuccessful()) {
                try {
                    Log.v(TAG, "headers = " + response.headers());

                } catch (Exception e) {
                    e.printStackTrace();
                }

                mAdapter = new RandomUserAdapter();
                mAdapter.setItems(response.body().getResults());
                recyclerView.setAdapter(mAdapter);
            } else if (response.code() == 504) {
                Log.v(TAG, "response body = " + response.raw().cacheResponse());
            }
        }

        @Override
        public void onFailure(Call<RandomUsers> call, Throwable t) {
            Log.v("cache-control", "response failure");
        }
    });
}

Итак, вот в чем проблема: приложение никогда не переходит в автономный блок кода в п.2. Если максимальный возраст все еще разрешен, используйте модифицированный ответ. Если ответ был кэширован некоторое время назад, а максимальный возраст недопустим, есть два случая:

1) Устройство подключено к сети:Retrofit сделать новый запрос к серверу (все ок)

2) Устройство находится в автономном режиме: метод обратного вызоваonFailure внутриnetworkCall() называется (стр.4 примеров кода)

Что не так в моем коде? Я действительно не понимаю, почему приложение не может использовать автономный случай контроля кэша.

Извините за слишком много текста. Спасибо!

Ответы на вопрос(1)

Ваш ответ на вопрос