3

I'm using Retrofit library from network calls. Pretty awesome. But I'm missing caching support. I can't using cache on HTTP layer (via Cache headers). Currently, I'm implementing custom caching with ObjectCache, but it's so complicated. It just should be awesome extend current Retrofit with @Cache(Expire.ONE_DAY) anotation.

My current code is like:

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());
            }
        });
    }
}

Now, it's just a lot of boilerplate code for each method.

Or do you know any library like Retrofit with caching support?

Thanks!

Radim Vaculik
  • 559
  • 4
  • 16
  • shouldn't that be automatic with the response headers? (you may need to use OkHttp with it to have disk cache, though) – njzk2 Jan 21 '15 at 20:11
  • see http://stackoverflow.com/questions/25887084/retrofit-okhttp-cache-https?rq=1 – njzk2 Jan 21 '15 at 20:11

1 Answers1

6

You can wrap the underlying Client and use the request URL as a cache key.

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;
  }
}

With Retrofit v2 we are looking to enable this kind of functionality with interceptors which will not only give you a hook into the request/response chain but also allow looking up a custom annotation like @Cache.

Jake Wharton
  • 75,598
  • 23
  • 223
  • 230