所以我尝试使用 Guava 缓存来缓存 HTTP 响应(使用 OkHtttp + 改造、rxjava 进行多线程)。目前看起来是这样的:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://blablabla.com")
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
apiClient = retrofit.create(Api.class);
CacheLoader<Integer, HttpResponse> cacheLoader = new CacheLoader<Integer, HttpResponse>() {
@Override
public Response load( Integer key ) throws InterruptedException, ExecutionException {
return apiClient.getHttpResponse(key)
.subscribeOn(Schedulers.io())
.blockingFirst();
}
};
responseCache = CacheBuilder.newBuilder()
.concurrencyLevel(8)
.maximumSize( 10 )
.build(cacheLoader);
apiClient 返回 Observable,并在 CacheLoader 的 load 方法中订阅它。我还设置了 concurrencyLevel(8)
但它似乎不允许同时“加载”和“读取”。
我认为 blockingFirst()
调用可能会阻塞线程,因此我无法从缓存发出并发请求,即每当缓存加载新的 http 响应时,都无法读取缓存。
我不知道如何使其异步,非常感谢任何帮助:)
最佳答案
使用Guava,您仍然可以进行异步非阻塞调用并缓存HTTP响应,但您必须在收到HTTP响应后手动调用cache.put()。所以你可以像下面这样定义你的LoadingCache。
private LoadingCache<String, ServerResponse> cache =
CacheBuilder.newBuilder()
.maximumSize(50)
.expireAfterWrite(24, TimeUnit.HOURS)
.build(
new CacheLoader<String, ServerResponse>() {
public ServerResponse load(String id) {
return null; // or empty ServerResponse
}
});
在你的调用方法中:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://blablabla.com")
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
apiClient = retrofit.create(Api.class);
try {
ServerResponse cachedResponse = cache.get(someUniqueKey);
if (cachedResponse != null) {
// return cachedResponse here
return;
}
doNormalHttpRequest()
} catch (ExecutionException | CacheLoader.InvalidCacheLoadException e) {
doNormalHttpRequest();
}
void doNormalHttpRequest() {
apiClient.request(body).enqueue(
new retrofit2.Callback<ServerResponse>() {
@Override
public void onResponse(Call<ServerResponse> call,
Response<ServerResponse> response) {
if (response.isSuccessful()) {
cache.put(someUniqueKey, response.body();
}
}
@Override
public void onFailure(Call<ServerResponse> call, Throwable {}
});
}
作为一个额外的好处,这也可以缓存 POST 请求,因为 Retrofit 仅使用 OkHttp 的缓存实现来缓存 GET 请求。
关于java - 如何使用Guava缓存HTTP响应? (没有线程被阻塞),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51244793/