我已经读过很多关于我的问题的问题和答案,但是我一直不知道如何解决.
我需要从服务器获取响应并将其存储在缓存中.之后,当设备离线时,我想使用缓存的响应.设备在线时,我想完全从服务器获取响应.
看起来没那么复杂.
这是我尝试执行此 *** 作的方式(代码示例):
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"); } });}
所以,这是问题所在:
该应用程序永远不会转到p.2中的离线代码块.
如果max-age仍然合法,则Retrofit使用缓存的响应.
如果响应是在一段时间前缓存的,并且max-age不合法,则有两种情况:
1)设备在线:翻新对服务器的新请求(一切正常)
2)设备离线:调用networkCall()内部的onFailure回调方法(代码示例的第4页)
我的代码有什么问题?我真的不明白为什么该应用程序不能使用脱机情况下的缓存控制.
抱歉,文本过多.
谢谢!
解决方法:
解决了.
诀窍在于结合拦截器和网络拦截器.
脚步:
1)将REWRITE_CACHE_CONTRol_INTERCEPTOR隔离为两个拦截器,一个拦截器用于在线工作,另一个拦截器用于离线工作:
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
OkhttpClIEnt okhttpClIEnt = new OkhttpClIEnt.Builder() .addInterceptor(httpLoggingInterceptor) //.addNetworkInterceptor(REWRITE_CACHE_CONTRol_INTERCEPTOR) .addInterceptor(OFFliNE_INTERCEPTOR) .addNetworkInterceptor(ONliNE_INTERCEPTOR) .cache(provIDeOkhttpCache()) .build();
Link to original article
总结以上是内存溢出为你收集整理的android-改造离线请求和响应全部内容,希望文章能够帮你解决android-改造离线请求和响应所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)