Android Networking I: OkHttp, Volley and Gson

Pablo Costa
AndroidPub
Published in
11 min readJul 12, 2015

--

A series of articles digging in the Android networking libraries.

Prologue

This is the first article of a series:

Assumptions

Motivation

There’s something that probably you can’t avoid in an Android project: Networking. Whether you are loading images, requesting data from an API server or getting a single byte from internet, you are doing networking.

No doubt there are a lot of good libraries out there and the wheel doesn’t need to be reinvented, but given how complex and omnipresent networking is on Android, one common question Android developers face when they start researching about networking is which libraries should I use? what’s the difference? what do I actually need?

On one side you have a bunch of small libraries focused on solving one specific problem that you can stack on top of each other and combine to achieve your needs.

On the other side you have some libraries that look more like a Swiss knife and can handle a lot of different scenarios related with networking. From HTTP client to image loading, and of course, REST helper.

The root of so many great networking libraries is that the offered options in the Android framework are not great and they were a mess to deal with in the old days (Eclair, Froyo and Gingerbread). You had to write a lot of boilerplate code each time you were doing requests, and probably you’ll be doing a sub-optimal (a.k.a. poor) job. This was the ideal scenario to solve once for all a really big and important problem so a lot of libraries started to appear and evolve.

In the old days networking in Android was a nightmare, nowadays the problem is to find out which solution fits better the project necessities.

This article talks about three libraries that play well with each other and will help you to cover most of your needs: OkHttp, Volley and Gson.

What is OkHttp?

OkHttp is an modern, fast and efficient Http client which supports HTTP/2 and SPDY. Reading how many things OkHttp does it’s a good way to understand how hard is to do networking: Connection pooling, gziping, caching, recovers from network problems, sync and async calls, redirects, retries … and so on.

OkHttp is a very capable networking tool out of the box, without the need of any REST library (Retrofit, Volley…) and probably is the library most developers would choose if they could only include one library in their projects.

OkHttp is an modern, fast and efficient Http client which supports HTTP/2 and SPDY and sits on top of Okio

OkHttp sits on top of Okio, a library that complements java.io and java.nio to make it much easier to access, store, and process your data. It provides fast I/O and resizable buffers.

One of the authors of Okio described it as the IO layer from OkHttp ripped out and made an standalone project.

OkHttp depends Okio (so you’ll have Okio in your project as well), but Okio can be used by its own.

Okio is the IO layer from OkHttp ripped out and made an standalone project

What is Volley?

Volley is a library that acts as an http client, REST helper and image loader. Takes care of requesting, loading, caching, threading, synchronization and some more stuff. It’s ready to deal with JSON, images, raw text and allow some customization.

Volley was design for RPC style network operations that populate the UI. Is good for short operations.

Volley by default uses as transport layer the Apache Http stack on Froyo and HttpURLConnection stack on Gingerbread and above. Nowadays there’s no many reasons to use those anymore and the good news is Volley allow us to easily set up OkHttp as its transport layer.

This is what Android networking looks like in Ficus Kirkpatrick (a Googler behind Volley) words. A lot of parallel async calls.

Volley is a library that acts as an http client, REST helper and image loader making it easier to deal with very common networking tasks

Volley wasn’t though for tasks like streaming of downloading big files.

What is Gson?

Gson is JSON serialization and deserialization library that uses reflection to populate your Java model objects from JSON objects. You can add your own serializers and deserializers as well to better control and customization.

OkHttp set up

OkHttp have strong defaults on purpose. By default it’s really fast and robust so app developers don’t need to go thru set ups. Transparent gzip, http/2, ssl… are turned on and are automatic.

Probably some of you would be interested in…

private int connectTimeout = 10_000;
private int readTimeout = 10_000;
private int writeTimeout = 10_000;

Those defaults can be modified via setters among a lot of other configs. Remember OkHttp can be used as an standalone for networking so it’s very powerful.

What’s interesting here is how to set OkHttp as the transport layer for Volley. To achieve that it’s necessary to create an implementation of a HttpStack. A HttpStack is an HTTP stack abstraction (interface) provided by Volley and in order to provide an our OkHttpStack implementation we can just grab this one.

OkHttpStack myOkHttpStack = new OkHttpStack(new OkHttpClient());

In the next section it’s described how to use this OkHttpStack in the Volley set up.

Volley set up

The way Volley works is creating requests and adding them to a queue. One queue is enough for the whole application, so each time you want to make a request you'll get the (only) Volley queue to add the request to that queue.

In the sample code (down blow) I’m using a global application singleton instance of the queue with the next method:

public RequestQueue getVolleyRequestQueue()
{
if (mRequestQueue == null)
{
mRequestQueue = Volley.newRequestQueue
(this, new OkHttpStack(new OkHttpClient()));
}

return mRequestQueue;
}

In the code above you can see like to create the request queue we are providing the OkHttpStack we talked in the section above.

If you don’t provide an HttpStack Volley will create an stack depending on your API level. This will be based on the AndroidHttpClient for API level 9 and below, and and HttpURLConnection for API level 10 and above.

Who do we add requests to the Volley requests queue?

public static void addRequest
(@NonNull final Request<?> request, @NonNull final String tag)
{
request.setTag(tag);
addRequest(request);
}
private static void addRequest(@NonNull final Request<?> request)
{
getInstance().getVolleyRequestQueue().add(request);
}

After adding those requests to the queue, Volley will take care of execute them.

One common problem tho, is that while a requests is been processed, the app navigates away that screen, so when the response is received, any access to the UI elements of that screen will cause NullPointerException because those values are null. That’s where cancellation comes handy. The requests should usually be cancelled on the onStop() callback of your activity/fragment.

public static void cancelAllRequests(@NonNull final String tag)
{
getInstance().getVolleyRequestQueue().cancelAll(tag);
}

You can specify a tag to a requests than can be use to cancel it.

Making requests

Let’s take a look at a JsonObject request:

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.GET,
mUrl,
new Response.Listener<JSONObject>()
{
@Override
public void onResponse(JSONObject response)
{
// Deal with the JSONObject here
}
},
new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error)
{
// Deal with the error here
}
});

App.addRequest(jsonObjectRequest, mTAG);

Good, but not great.

It’s not really useful to deal with JSON on this callbacks. What would be really handy is to have our model Java objects instead of a JSON object, and there is where Gson makes it appearance.

You are not alone in the Android networking world.

Gson set up

Let’s customize the request to get as responses Java objects that match our data model and we are more comfortable with. All it’s needed is a GsonRequest class extending the Volley Request like in this example.

The GsonRequest makes a get request and converts the response from JsonElement into a Java Object using Gson.

public static GsonRequest<DummyObject> getDummyObject
(
Response.Listener<DummyObject> listener,
Response.ErrorListener errorListener
)
{
final String url = "http://www.mocky.io/v2/55973508b0e9e4a71a02f05f";

final Gson gson = new GsonBuilder()
.registerTypeAdapter(DummyObject.class, new DummyObjectDeserializer())
.create();

return new GsonRequest<>
(
url,
new TypeToken<DummyObject>() {}.getType(),
gson,
listener,
errorListener
);
}

Here, we are creating an array of objects:

public static GsonRequest<ArrayList<DummyObject>> getDummyObjectArray
(
Response.Listener<ArrayList<DummyObject>> listener,
Response.ErrorListener errorListener
)
{
final String url = "http://www.mocky.io/v2/5597d86a6344715505576725";

final Gson gson = new GsonBuilder()
.registerTypeAdapter(DummyObject.class, new DummyObjectDeserializer())
.create();

return new GsonRequest<>
(
url,
new TypeToken<ArrayList<DummyObject>>() {}.getType(),
gson,
listener,
errorListener
);
}

The Gson parsing with a GsonRequest happens on a background thread, instead of the main thread.

To tell Gson how to deserialize the Json that is coming from the API, you can specify your own deserializers. You can check out how a simple deserializer looks like here.

In case you don’t provide deserializers Gson will try to make a matching between the field names and convert them into the target object type.

On both examples above we are making GET requests. For POST requests you can take a look at GsonPostRequest (how to use it) that it’s included in the code sample down below.

OkHttp works as the transport layer for Volley, which on top of OkHttp is a handy way of making network requests. Gson deserialize the responses into Java objects just before delivering them to the main thread

Loading images

Image loading in Android is as common as complex. Threading, requesting, transformations, resizing, memory management, caches… Probably we could right an entire article about it. Volley offers us one solution for this task.

NetworkImageView

Volley has a custom view called NetworkImageView (subclassing ImageView) on which you can set an URL, a default view holder and an error image.

Using it is as simple as:

mNetworkImageView = (NetworkImageView) itemView.findViewById(R.id.networkImageView);
mNetworkImageView.setDefaultImageResId(R.drawable.default_image);
mNetworkImageView.setErrorImageResId(R.drawable.error_image);
mNetworkImageView.setImageUrl(imageUrl, App.getInstance().getVolleyImageLoader());

As you can see, it’s possible to specify an error image (in case of error) and a placeholder (an image that is shown while loading the desired image).

The important bit in the code above is the setImageUrl method, which receives two parameters: the image URL and an ImageLoader. ImageLoader is a Volley helper that handles loading and caching images from remote URLs.

Let’s take a look at the getVolleyImageLoader method and how we can get an ImageLoader.

public ImageLoader getVolleyImageLoader()
{
if (mImageLoader == null)
{
mImageLoader = new ImageLoader
(
getVolleyRequestQueue(),
App.getInstance().getVolleyImageCache()
);
}

return mImageLoader;
}

private LruBitmapCache getVolleyImageCache()
{
if (mLruBitmapCache == null)
{
mLruBitmapCache = new LruBitmapCache(mInstance);
}
return mLruBitmapCache;
}

The only piece missing in this puzzle is LruBitmapCache. It’s a cache for bitmaps with less recent used policy.

Volley does not provide us with an implementation but we can get one from here that looks appropriate and handles the cache size per device specs, which is cool.

Remember the problem when not cancelling requests mentioned in a section above? How do we cancel NetworkImageView requests? We don’t. NetworkImageView takes care of the lifecycle of the request and cancels it when the view is detached.

ImageRequest

In some cases we are using other classes for holding our images. CircleImageView is a good example of it. So we can’t use NetworkImageView. In that case we'll use ImageRequest.

ImageRequests help us to request an image and access the bitmap.

final ImageRequest imageRequest =
new ImageRequest
(
sIMAGE_URL,
new Response.Listener<Bitmap>()
{
@Override
public void onResponse(Bitmap bitmap)
{
circleImageView.setImageBitmap(bitmap);
}
},
0,
0,
ImageView.ScaleType.CENTER_INSIDE,
Bitmap.Config.ARGB_8888,
new Response.ErrorListener()
{
public void onErrorResponse(VolleyError error)
{
circleImageView
.setImageResource(R.drawable.error_image);
}
}
);

App.getInstance().getVolleyRequestQueue().add(imageRequest);

ImageRequest takes in 7 parameters! Looks like a lot, but looking at them one by one is less scary.

  • String url: URL of the image we want to load.
  • Response.Listener<Bitmap> listener: on success listener. Give us access to the bitmap.
  • int maxWidth: Max width to decode the bitmap to
  • int maxHeight: Max height to decode the bitmap to
  • ScaleType scaleType: Same scaleType we use in our ImageViews.
  • Config decodeConfig: Bitmap config (ARGB_8888, RGB_565…)
  • Response.ErrorListener errorListener: Error listener

When you specify certain dimensions, what’s gonna happen is that the full image is downloaded but on the bitmap decoding the image will be resized to the specific size.

Tricks

  • You can pass the size of the target for lowering the memory footprint.
  • You can pass 0 on one of the dimensions to maintain the aspect ratio.
  • Use ARGB_565 instead of ARGB_8888 if doesn’t cause mayor quality impact on your images and you’ll lower the memory footprint.

In this case, again, we need to cancel the request on the onStop() method of our Activity/Fragment lifecycle.

Gradle dependencies in Android Studio

You need to add the next lines to your app’s build.gradle file.

compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.okhttp:okhttp:2.7.5'
compile 'com.android.volley:volley:1.0.0'

Note: The versions may be different as they are updated. Try to avoid + syntax on version numbers in order to have deterministic builds.

It´s not necessary to explicitly include the Okio dependency because OkHttp already has it. The Okio dependency looks like this:

compile 'com.squareup.okio:okio:1.9.0'

Update

As of SDK 23, apache http client was removed. Now it´s necessary to include the next line in the android section of your build.gradle:

useLibrary 'org.apache.http.legacy'

Final thoughts

The OkHttp/Volley/Gson solution is mature and was quite popular around 2013 and 2014 mainly for been a Google solution and appear in the Android Developers website and Google IO. It just works well and it’s fast, specially with images.

On the other hand, the documentation was always poor (still nowadays) and Volley has isn’t actively developed anymore (and for a while).

In my opinion, Volley is trying to achieve too many things: Http client, RESt helper and image loader. I prefer (arguably) separated libraries for separated purposes instead of one Swiss knife.

Interesting facts

  • All of the components we’ve talk about in this article (Okio, OkHttp, Volley and Gson) can be used as a standalone. They don’t need each other except OkHttp needing Okio.
  • One of the first articles I linked in the introduction (this one) was written by Jesse Wilson. Jesse Wilson is one of the guys behind Android’s HTTP, Gson, OkHttp and Okio.
  • OkHttp engine is backing HttpURLConnection as of Android 4.4. and many famous apps like Twitter, Facebook, Snapchat…
  • Volley was born as a solution to be used in the Google Play Store inside Google.
  • Both OkHttp and Okio are developed by the Square guys.
  • Gson (Google Json) is a project born at Google and still on the Google Github account where none of the current commiters are Googlers.

Resources

Code sample

--

--