Ant*_*pov 2 android caching retrofit okhttp
我已经阅读了很多关于我的问题的问题和答案,但我仍然无法理解如何解决它。
我需要从服务器获取响应并将其存储在缓存中。之后,当设备离线时,我想使用缓存响应。当设备在线时,我想从服务器准确获取响应。
看起来没那么复杂。
这是我尝试这样做的方式(代码示例):
1)创建缓存的方法
Cache provideOkHttpCache() {
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(this.getCacheDir(), cacheSize);
return cache;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
};
Run Code Online (Sandbox Code Playgroud)
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();
Run Code Online (Sandbox Code Playgroud)
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");
}
});
}
Run Code Online (Sandbox Code Playgroud)
所以,问题来了:应用程序永远不会进入第 2 页中的离线代码块。如果 max-age 仍然合法 Retrofit 使用缓存响应。如果响应是在一段时间前缓存的并且 max-age 不合法,则有两种情况:
1)设备在线:Retrofit
向服务器发出新请求(一切正常)
2)设备离线:调用onFailure
内部的回调方法networkCall()
(代码示例第4页)
我的代码有什么问题?我真的不明白为什么应用程序不能使用缓存控制的离线情况。
抱歉文字太多。谢谢!
解决了。
诀窍是结合Interceptor
和NetworkInterceptor
。
脚步:
1)分离REWRITE_CACHE_CONTROL_INTERCEPTOR用于两个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();
}
};
Run Code Online (Sandbox Code Playgroud)
2) okHttpClient 添加拦截器
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
//.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.addInterceptor(OFFLINE_INTERCEPTOR)
.addNetworkInterceptor(ONLINE_INTERCEPTOR)
.cache(provideOkHttpCache())
.build();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1576 次 |
最近记录: |