我在网络电话中使用Retrofit库。非常棒。但我缺少缓存支持。我无法在HTTP层上使用缓存(通过缓存头)。目前,我正在使用ObjectCache实现自定义缓存,但它太复杂了。它应该是通过@Cache(Expire.ONE_DAY)
anotation来扩展当前的Retrofit。
我目前的代码如下:
public static void getRestaurant(int restaurantId, String token, boolean forceNetwork, final Callback<Restaurant> listener) {
final String key = "getRestaurant-" + restaurantId + "-" + token;
Restaurant restaurant = (Restaurant) getCacheManager().get(key, Restaurant.class, new TypeToken<Restaurant>() {}.getType());
if (restaurant != null && !forceNetwork) {
Log.d(TAG, "Cache hit: " + key);
// Cache
listener.success(restaurant);
} else {
Log.d(TAG, "Network: " + key);
// Retrofit
getNetwork().getRestaurant(restaurantId, token, new retrofit.Callback<Response>() {
@Override
public void success(Response response, retrofit.client.Response response2) {
getCacheManager().put(key, response.result.restaurant, CacheManager.ExpiryTimes.ONE_HOUR.asSeconds(), true);
listener.success(response.result.restaurant);
}
@Override
public void failure(RetrofitError error) {
listener.failure(error.getLocalizedMessage());
}
});
}
}
现在,每个方法只需要很多样板代码。
或者你知道像Retrofit这样的库有缓存支持吗?
谢谢!
答案 0 :(得分:6)
您可以包装基础Client
并将请求URL用作缓存键。
public class CachingClient implements Client {
private final Client delegate;
@Override public Response execute(Request request) {
if (!"GET".equals(request.method())) {
return delegate.execute(request);
}
String url = request.url();
// TODO look up 'url' in your cache.
if (cacheHit) {
return createResponse(cacheResult);
}
// Cache miss! Execute with the real HTTP client.
Response response = delegate.execute(request);
// TODO cache 'response' in your cache with the 'url' key.
return response;
}
}
使用Retrofit v2,我们希望通过拦截器启用此类功能,这不仅可以为请求/响应链提供一个钩子,还可以查找像@Cache
这样的自定义注释。