Android Bricks: Networking

When it comes to networking I've seen two major solutions, one of which is almost always wrong. The first is doing it all by hand, possibly using HTTPUrlConnection or maybe OkHttp. While the latter is the better choice, most apps should be using a proper networking library.

There are  bunch of reasons to do this. First, its battle tested and better handles edge cases. Its probably threaded nicely and allows for automatic parsing or mapping from a server response to local native objects. It also handles pressure better than something you'd whip up in an hour or two. Further someone else takes the burden or maintaining and you can fix buts, meaning we all benefit. So what are your options?

Volley

This is Google's thing. At first blush it looks great, seems official, very easy use and integrate. Its pretty basic Java with callbacks. "Here's a url, fetch me some data, I'd like it in JSON," and thats that. A pretty basic set up looks like this.

// add in build.gradle
compile 'com.android.volley:volley:1.0.0'
val request = JsonObjectRequest(Request.Method.GET, url, null, 
    object: Response.Listener() {
        override fun onResponse(response: JSONObject) {
            // success!
        }
    }, 
    object : Response.ErrorListener() {
        override fun onErrorResponse(error: VolleyError) {
            // failure :(
        }
    })

So as you can see, its not too scary and tucks away all the threading and parsing for you. You can even have OkHttp power it, as to benefit from its handling of poor connections, support for more modern protocols, sensible defaults, and amazing flexibility should you need to dig deeper.

Retrofit

Defined with annotations Retrofit reduces boiler plate and clearly defines your API. It brings with it a plethora of converters, going far beyond JSON.org and String parsers. You can easily use GSON, Jackson, ProtocolBuffers, and more, simply by adding a line of code and a dependency. In my experience its also very good with memory and receives meaningful updates in a timely fashion.

// add in build.gradle
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile "com.squareup.retrofit2:converter-gson:2.1.0"
// define api
interface GitHubService {
  @GET("users/{user}/repos")
  fun listRepos(@Path("user") user: String): Call<List<Repo>>
}

// set up in a data manager
val retrofit = Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build()
val service = retrofit.create(GitHubService::class.java)

// actually fetch data
service.listRepos("octocat").enqueue(object: Callback<List<Repo>?> {
            override fun onResponse(call: Call<List<Repo>?>, response: Response<List<Repo>?>?) {
            // success!
            }

            override fun onFailure(call: Call<List<Repo>?>, t: Throwable?) {
            // failure :(
            }
        })

As you can see there is quite a bit more structure here and I think thats great. The relationship between an app should be structured. It should be clear and easy to understand yet powerful enough for the client to mutate requests and responses as needed to meet requirements.

Retrofit makes it easy to modify headers and deal with POST requests. Caching can be enabled fairly easily and it supports RxJava if thats something you're interest in. To be clear, much of this is provided by OkHttp but the proper integration between these two libraries works wonders.

Recommendation

Go with Retrofit and don't look back. In the rare case you'd decide to switch to something else it has such a clean API and easy to follow open source code that you'll be able to swap it out with ease. It has no discernible shortcomings and excels where Volley falls flat. With Volley I've experienced so much resistance to getting work done thats its not longer worth the effort maintaining on older projects. From leaks, to inflexible response processing. Retrofit just works and thats what you want when dealing with data.