Which HTTP library in Android to choose?

I present to you the translation of the article “ Which Android HTTP library to use? ".

What is it for?


Today, almost all applications use HTTP / HTTPS requests as a kind of transport for their data. Even if you do not directly use these protocols, many SDKs that you most likely have already included in your applications (for example, metrics, drop statistics, advertisements) use HTTP / HTTPS to work with the network. Today, there are very few libraries that a developer could freely use in his project. And I will try to talk about the main ones in this post.
Android developers have many reasons to opt for third-party libraries, instead of already built-in APIs such as HttpURLConnection or Apache Client. For instance:

  1. Ability to cancel a network call
  2. Parallel query execution
  3. Connection pool and reuse of existing socket connections
  4. Local caching of server responses
  5. Simple asynchronous operation interface to avoid blocking the main or UI threads
  6. Convenient wrapper over REST API
  7. Retry and Delay Policy
  8. Efficient image loading and transformation
  9. JSON serialization
  10. Support SPDY, http / 2

A bit of history


At the very beginning, Android had only 2 HTTP clients: HttpURLConnection and Apache HTTP Client. According to an official Google blog post, HttpURLConnection had several bugs in earlier versions of Android:
Prior to Froyo, the HttpURLConnection had some not-so-nice bugs. In particular, calling close () on a readable InputStream could ruin the connection pool.

At the same time, Google did not want to develop and migrate to the Apache HTTP Client:
... the large size of their API prevents us from improving this library without losing backward compatibility. The Android team does not work actively on the Apache HTTP Client.

Prior to Froyo, most developers preferred to use different clients based on the OS version:
Apache HTTP client has few bugs on Eclair and Froyo, so it is the best choice for these versions. And for Gingerbread and younger, HttpURLConnection is better. The simplicity of the API and low weight are well suited for Android. Transparent compression and caching of responses helps increase speed and save battery life. Newer applications should use HttpURLConnection.

Even today, if you look at the Volley source code from Google (I'll talk about it a bit later), you can find such a legacy:

if (stack == null) {
    if (Build.VERSION.SDK_INT >= 9) {
        stack = new HurlStack();
    }  else {
        // Prior to Gingerbread, HttpUrlConnection was unreliable.
        // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
        stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
    }
}

This is a classic example of Android fragmentation that makes developers suffer. In 2013, Square drew attention to this problem when it released OkHttp. OkHttp was created to work directly with the top level of Java sockets, without using any additional dependencies. It comes in the form of a JAR file, so developers can use it on any device with a JVM (where we include, of course, Android). To simplify the transition to their library, Square implemented OkHttp using the HttpUrlConnection and Apache client interfaces.



OkHttp gained widespread acceptance and community support, and in the end, Google decided to use version 1.5 in Android 4.4 (KitKat). In July 2015, Google officially recognized the Apache-based AndroidHttpClient as obsolete with the release of Android 5.1 (Lolipop).

Today, OkHttp comes with the following huge feature set:

  1. Support for HTTP / 2 and SPDY allows all requests going to the same host to share the socket
  2. Query aggregation reduces latency (if SPDY is not available)
  3. Transparent GZIP to reduce the weight of downloaded information
  4. Response caching avoids network operation during repeated requests.
  5. Support for both synchronized blocking calls and asynchronous calls with callback

My favorite part of OkHttp is how beautifully and accurately you can work with asynchronous requests:

private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://publicobject.com/helloworld.txt")
        .build();
    client.newCall(request).enqueue(new Callback() {
        @Override public void onFailure(Request request, Throwable throwable) {
        throwable.printStackTrace();
    }
    @Override public void onResponse(Response response) throws IOException {
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
        System.out.println(response.body().string());
    }
  });
}

This is very convenient, since working with the network should not be in the UI stream. In fact, starting with Android 3.0 (Honeycomb, API 11), working with a network in a separate thread has become mandatory. In order to implement something similar with HtttpUrlConnection, you will need to build a large (or maybe monstrous) construct using AsyncTask or a separate thread. This will be even more complicated if you want to add canceled downloads, merged connections, etc.

By the way, the HTTP library from Google called Volley, which provides us with the following bonuses, did not stay at the roadside:

  1. Automatic scheduling of network requests
  2. Many concurrent network connections
  3. Transparent caching in memory and on disk, in accordance with standard cache consistency.
  4. Query prioritization support.
  5. Cancel API requests. You can cancel both a single request and an entire block.
  6. Easy setup, for example, for repeats and deferrals.
  7. A strict sequence, which makes it easy to correctly populate with the data received asynchronously from the network, the user interface.
  8. Debugging and Tracing Tools



Whatever Volley is at the top of the HttpUrlConnection. If you want to get JSON or an image, then Volley has special abstractions on it, such as ImageRequest and JsonObjectRequest, which help you automatically convert the HTTP payload. Also noteworthy is that Volley uses a hard-coded network pool size:

private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;

When OkHttp uses a thread for every call with ThreadPoolExecutor with a maximum value of Integer.MAX_VALUE:

private int maxRequests = 64;
private int maxRequestsPerHost = 5;
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
      new LinkedBlockingQueue(), Util.threadFactory("OkHttp Dispatcher", false));

As a result, in most cases, OkHttp will act faster by using more threads. If for some reason you want to use OkHttp together with Volley, then there is an HttpStack implementation that uses the OkHttp request / response API instead of HttpURLConnection.

HTTP clients continued to evolve to support applications with a large number of images, especially those that support endless scrolling and image transformation. At the same time, the REST API became the industry standard, and each developer dealt with typical tasks such as serializing to / from JSON and converting REST calls to Java interfaces. Not much time passed before libraries appeared that solved these problems:

  1. Retrofit - type-safe HTTP Android client for interacting with REST-interfaces
  2. Picasso - a powerful library for downloading and caching images for Android

Retrofit provides a bridge between Java code and the REST interface. It allows you to quickly include HTTP APIs in your project, and generates a self-documenting implementation.

public interface GitHubService {
    @GET("/users/{user}/repos")
    Call> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .build();
GitHubService service = retrofit.create(GitHubService.class);

In addition to everything, Retrofit supports conversion to JSON, XML, protocol buffers.

Picasso, on the other hand, provides an image-oriented HTTP library. For example, you can load an image into your View with one line:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

Picasso and Retrofi are configured to use OkHttpClient as a standard HTTP client. However, if you want, you can specify the HttpURLConnection client.

Glide is something similar to Picasso. It provides some additional features, such as GIF animation, thumbnail generation, and still videos. A full comparison can be found here .

Facebook recently revealed to the public the source code of the Fresco library, which they use in their mobile application. One of the key features that makes it stand out is its custom memory allocation strategy for bitmaps to avoid a long GC (garbage collector). Fresco allocates memory in a region called ashmem. Some tricks are used to have access to this region of memory access both from the part written in C ++, and from the part in Java. To reduce the consumption of CPU and data from the network, this library uses 3 cache levels: 2 in RAM, the third in internal storage.



I found it necessary to show the relationship between libraries on the same diagram. As you can see, HTTP always stays at the bottom of high-level libraries. You can choose between a simple HttpUrlConnection or the latest OkHttpClient. We use this compatibility when developing the PacketZoom Android SDK, which we will talk about in the next post.



Recently, we compared HTTP libraries with each other for performance , but this topic deserves a separate consideration. We hope this review gave you basic ideas about the pros and cons of each library, and we helped you make the right choice. Stay tuned for more interesting Android networking posts from us.

Also popular now: