Conclusion of my adventures with Retrofit 2

Mateusz Dziubek
AndroidPub
Published in
3 min readOct 28, 2016

--

Over the last few months as a beginning Android developer I had quite a few clashes with Retrofit. After being scolded by my mentor for not reading docs, being pissed off about backend guys in my team for not cooperating with me, being mistaken for a long time that Cache-Control is a magic header you can’t add to server’s response by yourself and finally after being scared, that all of the advice I got about REST and OkHttpClient will just fade away over time I decided to write this post as sort of a letter to the “future me” to keep all pro tips in one place. So without further ado…

Mock your web API with Flask

Flask is a microframework for Python which can be used to mock API endpoints during early development stage of an app. Below is a minimal example I implemented to help me explore Retrofit further:

Tips:

  • To make a server with your data visible externally, after exporting variable FLASK_APP (which is dataAPI.py in my case), you simply need to enter this command: flask run --host=0.0.0.0.
  • If other devices can’t see your server check if you are connected to the same network and if you are using port number (default :5000) in your URL.
  • You can add headers to your response with resp.headers['your_header'] = 'your_value'.

Don’t overcomplicate you data model

I know it might be tempting to rely on json-to-POJO converters such as this or this. However, you should consider minimizing:

Why? Because you can use…

Deserializers

JsonDeserializers provide a way to access your json directly and manipulate data from within its keywords:

Tips:

  • Don’t forget about testing your deserializers. You can extend your test class from the base class that will load static json resources from app/src/test/resources
  • Essentially what you’re testing is a Gson object
  • In case of a JsonArray use:
registerTypeAdapter(new TypeToken<List<DataModel>>() {}.getType(), new DataDeserializer())

Keep you Gradle clean

One fancy trick to keep in mind AND in your build.gradle file:

ext {
retrofitVersion = '2.1.0'
}
compile “com.squareup.retrofit2:retrofit:$retrofitVersion”
compile “com.squareup.retrofit2:converter-gson:$retrofitVersion”

Online caching using interceptors

Below is the proper way to implement online response cache when server is not returning Cache-Control header:

Tips:

  • Don’t forget to first set cache on your OkHttpClient:
File httpCacheDirectory = 
new File(getApplicationContext().getCacheDir(), "okHttpCache");
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(httpCacheDirectory, cacheSize);
  • This interceptor needs to be added as a NETWORK inteceptor (addNetworkInterceptor(new OnlineCacheInterceptor()).
  • maxAge is simply the time our response is considered “fresh” by cache.

Offline caching using interceptors

In contrast to the previous interceptor, we’ll modify Request object and check if network is available:

Tips:

  • Don’t forget to first set cache on your OkHttpClient:
File httpCacheDirectory = 
new File(getApplicationContext().getCacheDir(), "okHttpCache");
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(httpCacheDirectory, cacheSize);
  • This interceptor needs to be added as a REGULAR inteceptor (addInterceptor(new OfflineCacheInterceptor()).
  • maxStale indicates that even if the “freshness” time given by maxAge expires, the cache will still use this response for a given period of time.

--

--

Mateusz Dziubek
AndroidPub

Senior software engineer with acute product sense and business knowledge