This is just one more example about how in Kotlin we can continue to use the same libraries we’ve always used in Java for Android.

Retrofit is a library that greatly simplifies doing requests to an API, and in this case I’m going to teach you how to integrate it with some LastFM API requests. You can see the full code working in the Bandhook Kotlin repository.

If you want to start today, I recommend you take a look at my free training, where you will have an hour and a half of content to know what are your next steps to become an expert in Kotlin.

Retrofit 2 in Kotlin

The code in Kotlin is going to be very similar to what we would use in Java. We’ll see more in detail what are some of their differences, but you’ll see that everything is pretty easy and intuitive.

And we’ll also create some very useful extension functions, you’ll see.

Also, Retrofit recently can be used in combination with Kotlin Coroutines. If you’re interested in this, please let me know in the comments and I’ll write about it.

Build the build.gradle

I won’t stop here too much, but you need to add the following instructions to build.gradle:

Join my free 2-hour training!

  • Learn how to start and use a more idiomatic Kotlin in a breeze
  • Find out what's the current situation of Kotlin in the market
  • Get 2 free ebooks just for attending!
compile "com.squareup.okhttp3:okhttp:$okhttpVersion"
compile "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"

compile ("com.squareup.retrofit2:retrofit:$retrofitVersion"){
    // exclude Retrofit’s OkHttp peer-dependency module and define your own module import
    exclude module: 'okhttp'
}
compile "com.squareup.retrofit2:converter-gson:$retrofitVersion"

The first dependencies include the latest version of OkHttp and a logging interceptor, which can be useful for debugging.

The following add Retrofit (excluding OkHttp, so we have control over the version we use), and the Gson converter to convert requests to classes.

Create the communication interface

This is the neuralgic part of Retrofit. It’s where you specify the structure of the requests, which will have to match the API:

interface LastFmService {

    @GET("/2.0/?method=artist.search")
    fun searchArtist(@Query("artist") artist: String): Call

    @GET("/2.0/?method=artist.getinfo")
    fun requestArtistInfo(@Query("mbid") id: String, @Query("lang") language: String): Call

    @GET("/2.0/?method=artist.gettopalbums")
    fun requestAlbums(@Query("mbid") id: String, @Query("artist") artist: String): Call;

    @GET("/2.0/?method=artist.getsimilar")
    fun requestSimilar(@Query("mbid") id: String): Call

    @GET("/2.0/?method=album.getInfo")
    fun requestAlbum(@Query("mbid") id: String): Call
}

It’s quite simple. It identifies the type of the request with the notation, and then the parameters of the request as arguments of the function.

In Retrofit 2, we need to return objects of type Call.

Initialization of the communication service

First you can initialize the OkHttp client as follows:

val client = OkHttpClient().newBuilder()
    .cache(cache)
    .addInterceptor(LastFmRequestInterceptor(apiKey, cacheDuration))
    .addInterceptor(HttpLoggingInterceptor().apply {
        level = if (BuildConfig.DEBUG) Level.BODY else Level.NONE
    })
    .build()
}

Here we can see the use of the function, apply, which will help us initialize the interceptor in the style of a builder, without the need for the class to implement any type of builder.

The LastFmRequestInterceptor has nothing remarkable, but you can take a look on Github. The creation of the service has nothing different to Java:

val retrofit = Retrofit.Builder()
        .baseUrl("http://ws.audioscrobbler.com")
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

val lastFmService = retrofit.create(LastFmService::class.java)

Make your first request

Due to the need for Call in Retrofit 2, it becomes a bit more tedious code:

val call = lastFmService.requestAlbums(mbid, name)
val result = call.execute().body()
val albums = AlbumMapper().transform(result.topAlbums.albums)

However, thanks to the extension functions, we can create a function on Call to retrieve the values, like this:

val albums = lastFmService.requestAlbums(mbid, name).unwrapCall { 
    AlbumMapper().transform(topAlbums.albums)
}

Much simpler, right?

What is the form of unwrapCall?

inline fun <T, U> Call.unwrapCall(f: T.() -> U): U = execute().body().f()

It’s a function that extends Call class. It will execute the request, retrieve the body, and make this one (which will be of type U) execute the function f().

In the above example T is LastFmResponse and U is List.

Conclusion

With this example I wanted to show you once again that any of the Java libraries you know and love can be used in Kotlin without issues.

Also, far from making things more complicated, in most cases the language will simplify the code.

Still not convinced about Kotlin for Android? Start using it as soon as possible! Thanks to the previous articles you can learn more about Kotlin, or I recommend that you sign up to my free training here.

%d bloggers like this: