【发布时间】:2018-06-19 15:32:06
【问题描述】:
我真的被这个问题困住了。
我想缓存服务器响应一段时间以在设备离线时使用数据。
所以我为我的OkHttpClient 设置了一个缓存。
我还设置了Cache-Contlol 标头。
这是我的代码:
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;
}
}
看起来一切都会好起来的。 然后我这样做:
- 运行应用程序
- 查看 OkHttp 日志和屏幕以确保我们已成功接收数据
- 关闭应用
- 在设备上开启飞行模式(所有网络关闭)
- 运行应用程序
此时我预计该应用将使用缓存数据。但事实并非如此。
我的 logcat 中只有空白屏幕和 HTTP FAILED: java.net.UnknownHostException: Unable to resolve host "randomuser.me": No address associated with hostname。
【问题讨论】:
-
我从未使用过缓存控制。但是当应用程序关闭时它会保存任何东西吗?不只是在应用仍然打开但您想再次拨打电话时?
-
@Eselfar 据我所知,缓存在关闭应用程序后不会被删除。而且看起来问题不在于关闭应用程序。我在我的 MainActivity 中添加了一个按钮,当点击它时会运行一个新的响应。所以在 logcat 中我看到来自服务器的新响应而不使用缓存。真的卡住了……