OkHttp 3响应缓存(java.net.UnknownHostException) [英] OkHttp 3 response cache (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:
- 运行应用
- 在OkHttp日志和屏幕上查看,以确保我们已成功接收数据
- 关闭应用
- 打开设备上的飞行模式(所有网络均关闭)
- 运行应用
目前,我希望该应用将使用缓存的数据.但事实并非如此.
我的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屋!