OkHttp 3响应缓存(java.net.UnknownHostException) [英] OkHttp 3 response cache (java.net.UnknownHostException)

查看:173
本文介绍了OkHttp 3响应缓存(java.net.UnknownHostException)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的陷在这个问题上了.

I'm really stuck at this problem.

我想将服务器响应缓存一段时间,以便在设备离线时使用数据. 因此,我将缓存设置为OkHttpClient. 我还设置了Cache-Contlol标头.

I want to cache server response for some time to use the data when device is offline. So I set a cache to my OkHttpClient. Also I set Cache-Contlol header.

这是我的代码:

    public class MainActivity extends AppCompatActivity {

    Retrofit retrofit;
    RecyclerView recyclerView;
    RandomUserAdapter mAdapter;
    Cache cache;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();

        GsonBuilder gsonBuilder = new GsonBuilder();
        Gson gson = gsonBuilder.create();

        cache = provideOkHttpCache();

        Timber.plant(new Timber.DebugTree());

        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                populateUsers();
            }
        });

        Interceptor cacheInterceptor = new Interceptor() {
            @Override
            public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
                okhttp3.Response originalResponse = chain.proceed(chain.request());
                okhttp3.Response modifyedResponse = originalResponse;

                if (true) {
                    modifyedResponse = originalResponse.newBuilder()
                            .header("Cache-Control", "max-age=86400")
                            .build();
                }

                return modifyedResponse;
            }
        };

        HttpLoggingInterceptor httpLoggingInterceptor = new
                HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(@NonNull String message) {
                Timber.i(message);
            }
        });

        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient okHttpClient = new OkHttpClient()
                .newBuilder()
                .addInterceptor(httpLoggingInterceptor)
                .addInterceptor(cacheInterceptor)
                .cache(cache)
                .build();

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

        populateUsers();

    }

    private void initViews() {
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        button = findViewById(R.id.button);
    }

    private void populateUsers() {
        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()) {
                    Log.v("cache-control", "using cache = " + isFromCache(response));
                    mAdapter = new RandomUserAdapter();
                    mAdapter.setItems(response.body().getResults());
                    recyclerView.setAdapter(mAdapter);
                }
            }

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

    public RandomUsersApi getRandomUserService() {
        return retrofit.create(RandomUsersApi.class);
    }

    Cache provideOkHttpCache() {
        int cacheSize = 10 * 1024 * 1024; // 100 MiB
        File cacheDir = new File("cachedirectory");
        Cache cache = new Cache(cacheDir, cacheSize);
        return cache;
    }

    public boolean isFromCache(Response response) {
        return response.raw().cacheResponse() != null;
    }
}

看起来一切都会好起来的. 然后我这样做:

Looks like everything is going to be ok. Then I do this:

  1. 运行应用
  2. 在OkHttp日志和屏幕上查看,以确保我们已成功接收数据
  3. 关闭应用
  4. 打开设备上的飞行模式(所有网络均关闭)
  5. 运行应用

目前,我希望该应用将使用缓存的数据.但事实并非如此. 我的logcat中只有空白屏幕和HTTP FAILED: java.net.UnknownHostException: Unable to resolve host "randomuser.me": No address associated with hostname.

At this moment I expect that app is going to use cached data. But it doesn't. I have only blank screen and HTTP FAILED: java.net.UnknownHostException: Unable to resolve host "randomuser.me": No address associated with hostname in my logcat.

推荐答案

好,我找到了解决方案.我不知道为什么会这样,但确实会这样. 首先,我们需要修改cacheInterceptor的创建:

Well, I found the solution. I'm not sure why does it work, but it really does. First we need to modify creation of cacheInterceptor :

        Interceptor cacheInterceptor = 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 = 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();
                }
            }
        };

然后我们需要使用addNetworkInterceptor(Interceptor interceptor)代替addInterceptor(Interceptor interceptor):

Then we need to use addNetworkInterceptor(Interceptor interceptor) instead addInterceptor(Interceptor interceptor):

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

原始答案:使用Retrofit 2.0和okhttp3进行缓存

这篇关于OkHttp 3响应缓存(java.net.UnknownHostException)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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