改造离线请求和响应 [英] Retrofit offline request and response

查看:77
本文介绍了改造离线请求和响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了许多有关该问题的问题和答案,但我一直不知道如何解决.

I've already read many questions and answers about my issue, but I slill can't understand how to solve it.

我需要从服务器获取响应并将其存储在缓存中.之后,当设备离线时,我想使用缓存的响应.设备在线时,我想完全从服务器获取响应.

I need to fetch response from server and store it in cache. After that when device is offline I want to use cached response. When device is online I want to fetch response exactly from server.

看起来并不复杂.

这是我尝试执行此操作的方式(代码示例):

Here is the way (samples of code) I try to do this:

1)创建缓存的方法

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

2)创建一个拦截器来修改缓存控制标头

2)Create an Interceptor to modify cache-control headers

 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并进行改进

3) Create OkHttpClient and Retrofit

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)进行网络通话的方法

4) Method to make a network call

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");
        }
    });
}

所以,这是问题所在: 该应用程序永远不会转到p.2中的脱机代码块. 如果max-age仍然合法,则Retrofit使用缓存的响应. 如果响应是在一段时间前缓存的,并且max-age不合法,则有两种情况:

So, here is the problem: The app never goes to the offline block of code in p.2. If max-age is still legal Retrofit use cached response. If response was cached some time ago and max-age is not legal there is two cases:

1)设备在线:Retrofit向服务器发出新请求(一切正常)

1) Device is online: Retrofit make new request to server (everything is OK)

2)设备处于脱机状态:调用了networkCall()中的回调方法onFailure(代码示例的第4页)

2)Device is offline: Callback method onFailure inside networkCall() is called (p.4 of code samples)

我的代码有什么问题?我真的不明白为什么应用程序不能使用缓存控制的脱机情况.

What's wrong in my code? I really don't understand why the app cant use offline case of cache-control.

抱歉,文本太多. 谢谢!

Sorry for too much text. Thanks!

推荐答案

已解决.

诀窍在于结合InterceptorNetworkInterceptor.

步骤:

1)将REWRITE_CACHE_CONTROL_INTERCEPTOR隔离为两个拦截器,一个拦截器用于在线工作,另一个拦截器用于离线工作:

1)Separate REWRITE_CACHE_CONTROL_INTERCEPTOR for two Interceptors, one for online work and other for offline work:

Interceptor OFFLINE_INTERCEPTOR = new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!isOnline()) {
                    int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                    request = request.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            .build();
                }

                return chain.proceed(request);
            }
        };


Interceptor ONLINE_INTERCEPTOR = new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                okhttp3.Response response = chain.proceed(chain.request());
                 int maxAge = 60; // read from cache
                return response.newBuilder()
                         .header("Cache-Control", "public, max-age=" + maxAge)
                        .build();
            }
        };

2)将拦截器添加到okHttpClient

2)Add Interceptors to okHttpClient

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

链接到原始文章

这篇关于改造离线请求和响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆