API request in Android the easy way using Kotlin

Kotlin is a really powerful language aimed to write more code using less boilerplate. And this is specially true in Android. Apart from the language itself and its own classes, Kotlin also provides a good set of useful extensions for already existing Java classes. An example of this is the way to make a request to an API and download the result.

I know that a lot of different libraries already exist to help us do this task, and Kotlin can make use of them because of its interoperability with Java, but we sometimes use big libraries to commit small requirements only because it’s much simpler and less prone to errors.

API Request: Java vs Kotlin

I always like to compare both languages to see what we are missing by sticking to Java. The typical code to recover a json from an url is this:

[java]
try {
URL url = new URL("<api call>");

urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();

InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));

String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}

if (buffer.length() == 0) {
return null;
}
result = buffer.toString();
} catch (IOException e) {
Log.e("Request", "Error ", e);
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("Request", "Error closing stream", e);
}
}
}
[/java]

Kotlin standard library provides an extension function for URL class that prevents us from having to write all that code. Previous code can be converted to:

[scala]
val result = URL("<api call>").readText()
[/scala]

This function is not recommended for huge responses, but it will be enough in most situations. If it is not, there are many other interesting extension functions such as BufferedReader.forEachLine(), which creates a Sequence of the lines and let us do something with any of them. Or you can get the raw Sequence by using BufferedReader.lineSequence(). From this moment, you could perform any of the different transformations a Sequence allows, such as filtering, sorting, mapping, etc.

Asynchronous call

As you know, the main thread is in charge of UI rendering and interaction, and we shouldn’t block it with long tasks, because the UI performance will be affected. In the case of HTTP requests, even the Android SDK will prevent us from doing it by throwing an exception. The typical solution in Android is the use of AsyncTask. An AsyncTask has an abstract method called doInBackground, which is executed in a secondary thread.

Apart from the fact that it’s really difficult to make an AsyncTask work properly, because of the many problems it brings with itself, it’s really tedious to create a new class which extends from it, cancel it in onDestroy, etc. A very simple version of this (you’d probably need more checks to avoid crashes) would be:

[java]
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

task = new AsyncTask<Void, Void, String>() {
@Override protected String doInBackground(Void… params) {
return requestFromServer("<api call>");
}

@Override protected void onPostExecute(String s) {
if (!isFinishing() && !isCancelled()) {
Log.d("Request", s);
Toast.makeText(ExampleActivity.this, "Request performed", Toast.LENGTH_LONG).show();
}
}
};
}

@Override protected void onDestroy() {
super.onDestroy();

if (task != null) {
task.cancel(true);
task = null;
}
}
[/java]

Not really clean nor intuitive. When we are working with Kotlin in Android, a library we can’t miss is Anko. It’s main goal is to provide a DSL to create layouts using code instead of XML. I’m really used to XML, so at the moment I don’t use it for that, but it includes a whole set of extremely useful features. In particular, there’s a small DSL for asynchronous tasks. The previous code could be reduced to this in Kotlin:

[scala]
async {
val result = URL("<api call>").readText()
uiThread {
Log.d("Request", result)
longToast("Request performed")
}
}
[/scala]

Basically you have an async function that will execute it’s code in another thread, and will give the chance of returning main thread using uiThread. async is an extension function implemented for Context, and will use a weak reference of it, so it won’t prevent GC from releasing its memory.

The good part about uiThread is that it’s implemented differently depending on the class it uses. If we call it from an Activity, the uiThread code won’t be executed if activity.isFinishing() returns true, and it won’t crash in that situation.

async returns a java Future, in case you want to work with futures. And if you need it to return a future with a result, you can use asyncResult.

You also can use your own executor:

[scala]
val executor = Executors.newScheduledThreadPool(4)
async(executor) {
// Some task
}
[/scala]

Conclusion

With a few lines of code, we’re getting the same (if not better) result from a very typical operation such as making an API call and get its result in a String variable. There’s a lot of interesting code behind these extension functions, so I recommend you to review the source code of Kotlin and Anko, and see what’s doing behind the scenes.

And remember you can learn this and many other things about Kotlin in the book I’m writing: Kotlin for Android Developers, where you will learn Kotlin by creating an Android App from the ground up.

24 thoughts on “API request in Android the easy way using Kotlin”

    1. Nice lib. But I’m not sure about extensions over String you’ve added. Escpecially about get(). This method name is usually reserved for accessing collection items and can be replaced with square braces []. And may be in the future JetBrains will reserve String.get/put/delete for some useful methods.
      That’s why I think that public libraries shouldn’t be so bold, impudent if you wish.

      1. Thanks for your constructive suggestions. Yup I was so bold doing that as I feel like extension functionality of Kotlin is just too awesome to not being used. If so, should I rename it into `httpGet` just to be clear?

        (This might be a bit too spammy to discuss it in @antonioleiva blog)

      2. Is there a way to do error handling with this? or get a status code. I tried a try catch block but unfortunately it didn’t work

      1. It depends on where you use that code. The config changes can be dealt in many different ways (singletons, loaders, retained fragments, persistence…)

  1. Thank you for this article. I started with Kotlin a few day ago. Your site is very helpful for me. I hope that you would write more stuff soon. Great work ! 🙂

    1. What does “exp” mean? I haven’t used this very deeply (it’s really for very simple things), but it probably returns an exception that you can capture with a regular try/catch.

  2. Hi Antonio,
    I’m just starting with Kotlin in Android Studio. I don’t understand what you mean by the “Kotlin standard library”. If it’s standard, do I have to somehow import it? Same goes with Anko.

    Thing is, if I write URL(“…”).readText() I got is a red underline that says I have to import something like javsa.net.URL which I’m pretty sure it isn’t what I’m looking for (it doesn’t work on runtime).

    So… is it possible to write something more explicitly, or maybe point me to somewhere else where I can find it?

    Thanks!

Comments are closed.