Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invalidate/force update of cache route at next request with Retrofit and OKHttp?

I'm using Retrofit with OKHttp client for caching responses from a JSON API.

This works nicely.

However, if I take an action on the device which causes the data to update on the server I need a way to 'invalidate' a particular route in order to ensure that next time a request is made for this data, it is fetched from the server again rather than the now outdated cached version.

Currently, I've worked around this by explicitly calling the new route with a "no-cache" flag in the Cache-Control header of the request, but this forces me to download the new data before it is needed, potentially multiple times if multiple actions are taken, just to keep the cache up to date.

Is there a way I can mark a route / method in my retrofit/OKhttp client as cache expired, requiring a mandatory update over the network the next time it's requested?

like image 458
Shaun Avatar asked May 21 '14 11:05

Shaun


People also ask

Which is better OkHttp or Retrofit?

You should use retrofit if you are trying to map your server API inside your application (type-safing). Retrofit is just an API adapter wrapped over okHTTP. If you want to type safe and modularise the interaction code with your API, use retrofit.

Does Retrofit support caching?

You cannot cache POST requests. Only GET requests can be cached. Inside the interceptors, you need to get chain. request() to get the current request and add Cache options to it.

Does Retrofit need OkHttp?

For making HTTP requests Retrofit uses the OkHttp library. OkHttp is a pure HTTP/SPDY client responsible for any low-level network operations, caching, requests and responses manipulation.


4 Answers

To quote the official code sample using urls():

val urlIterator = cache.urls()
    while (urlIterator.hasNext()) {
      if (urlIterator.next().startsWith("https://www.google.com/")) {
        urlIterator.remove()
      }
    }
like image 198
Sam Avatar answered Oct 14 '22 07:10

Sam


With retrofit2 and OkHttp3 you can force a new response by adding a Cache-Control header to your API method definition parameters:

@GET("ws/something")
Something getSomething(@Header("Cache-Control") String cacheControl);

and then when calling you either supply null for a (maybe-)cached version or "no-cache" for a live version:

myApi.getSomething(forceRefresh ? "no-cache" : null);
like image 42
whlk Avatar answered Oct 14 '22 05:10

whlk


This is now possible in OkHttp by using the Cache.urls() function. As the documentation says:

The iterator supports Iterator.remove(). Removing a URL from the iterator evicts the corresponding response from the cache. Use this to evict selected responses.

This was merged into master late December 2014 and seems to be part of these tags (releases): parent-2.4.0-RC1 parent-2.4.0 parent-2.3.0 parent-2.2.0

like image 45
Espen Riskedal Avatar answered Oct 14 '22 06:10

Espen Riskedal


There isn't an API for this, but there should be one. Please open an OkHttp issue to report this.

It'll probably take a while for us to implement because we'll need to figure out what the best API for this is. Invalidating a single URL is straightforward. Invalidating a range of URLs (say square.com/cash/*) is more difficult because OkHttp's cache is currently organized by URL checksums. There's also ugly edge cases like what happens if the invalidated URL is currently being written to the cache.

like image 32
Jesse Wilson Avatar answered Oct 14 '22 05:10

Jesse Wilson