Android – Wait for two networks requests to finish with Kotlin

In Android, UI operations happen in the main thread while longer running operations such as network requests and database transactions happen in the background thread.

When building mobile apps against public APIs, there are times where you have to make a network request to multiple endpoints in a single screen, but only display the entire screen once all of the network requests have completed. As mentioned at the beginning of this post, network requests are done in a separate thread, which is usually managed by whatever networking libraries you are using (it’s probably Retrofit), RxJava, or if you’re doing it manually in an AsyncTask.

Threads are hard. I don’t like threads. I have a difficult time understanding it, working with it, and managing it. Slight mismanagement of it can lead to all kinds of issues like race condition where it can become annoying enough to debug where you’ll want to flip a table. As mentioned above, when you have to build an a screen in a mobile app where you have to make a network request to more than one endpoint at a time, and only commence an operation (like displaying data on a screen) once all of the network requests have finished, you’ll have to figure out how to listen for when different requests, essentially threads, have finished loading.

There are multiple ways of going about this in Android. Some people will say look into CountDownLatch while some people will say to learn RxJava. While both suggestions will work, CountDownLatch looks too complicated for me to bother understanding and RxJava has too high of a learning curve for it to be a viable option if you need to learn how to do this quickly. If you use Kotlin, you can also look into coroutines but that’s apparently an experimental feature according to JetBrains.

While trying to figure out how to do this I found a Kotlin library called Kovenant that makes asynchronous operations super easy on Kotlin. If you’re unfamiliar with promises and asynchronous calls, the TLDR is that you run some code asynchronously and promises allow you to commence the next sequence of operation once that initial asynchronous operation has finished running. Kovenant also makes it easy to combine multiple promises, which is what we’ll be using to wait until two network operations are finished before commencing our UI operations. Let’s look at some code sample from the redesign I’m working on for MaterialReads.

In this redesign, I need to have data from two different endpoints: updates and reviews. Unfortunately, GoodReads do not provide an endpoint that reads both datasets in one API call, thus I have to make two. I want to be able to display a loading spinner while data from both endpoints are being loaded and then hide the loading spinner only if the two network requests have finished running its full course. This would be difficult to do manually but Kovenant makes it easy. As displayed in the code sample, we split the both network requests into two separate methods, and then create a deferred object. We only resolve the deferred object if the request has been successful in each network request.

In our refresh method, we can combine the two promises, which will allow us to wait until two network requests have finished loading and load the updates and reviews that have been retrieved from the API. In this example, we’re only combining two promises, but Kovenant allows you to combine up to 20 promises at a time.

If you Google how to wait and detect if multiple asynchronous operations have finished, you’ll get slews of answers that range from very manual (which also can mean error prone) to something like “just learn RxJava and reactive programming”. I found that the using something like Kovenant and its easy to use promises is the best way to solve this problem of asynchronous callbacks.