Api Client using Retrofit, RXJava and Kotlin

For last year since I found about Kotlin I’m learning how to use it in Android app development, Spring framework etc. I’m still amazed how expressive and functional this programming language is compared to our old friend Java. Kotlin is constantly updated with new features and it’s getting better and more popular every day.

I’m using angular and other javascript frameworks like vue in my work. I just love how easy is to work with API data with angular’s HttpClient, rx observables and other great tools packed with it. With few lines of code you get so much done. Now with Kotlin, Retrofit and RXJava you can do almost same in android development. In this tutorial I’ll try to show you just few cool and useful possibilities.

In this tutorial we will make simple client app which will consume API data from JSONPlaceholder API.


We will start by creating new project in Android Studio, include Kotlin support and choose Empty Activity for start.

Setup

Add Retrofit and RXJava dependencies in build.gradle(Module:app) file and Sync.

build.gradle(Module:app)
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

Add Internet permision in AndroidManifest.xml to get internet access.

AndroidManifest.xml
   <uses-permission android:name="android.permission.INTERNET"/>

API

Our project is now setup and ready now it’s time for some magic. As I said before this app will consume data from JSONPlaceholder API. We will use https://jsonplaceholder.typicode.com/posts endpoint to get list of articles. If you open this link in your browser you will get list articles as json objects.

GET FROM https://jsonplaceholder.typicode.com/posts
[
    {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
   },
   {
        "userId": 1,
        "id": 2,
        "title": "qui est esse",
        "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
   },
   {
       "userId": 1,
       "id": 3,
       "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
       "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
}, ...

Sending POST request to https://jsonplaceholder.typicode.com/posts with article in request body will add new article. If we pass article ID as path parameter we will get single article object in API response.

POST TO https://jsonplaceholder.typicode.com/posts/11
{
    "userId": 2,
    "id": 11,
    "title": "et ea vero quia laudantium autem",
    "body": "delectus reiciendis molestiae occaecati non minima eveniet qui voluptatibus\naccusamus in eum beatae sit\nvel qui neque voluptates ut commodi qui incidunt\nut animi commodi"
}

Article

We can use this response to define our Article class to which we will map our json objects from response.

Create new Kotlin file and define Article class.

Article.kt
data class Article(
        val userId: Int,
        val id: Int,
        val title: String,
        val body: String
)

Article API Client

If you used Retrofit with Java before you know that we need to define interface where we will describe our HTTP requests, functions to trigger those requests and expected response types. In Kotlin it is similar but there is’t so much code and it’s really easy. In our ArticleApiClient interface we will define:

    GET request for returning list of Articles
    GET request to return Article by it’s id
    POST request to add new Article

All requests will return Observables to which we will have to subscribe later by using RXJava . Create new Kotlin file and define ArticleApiClient interface:

ArticlesApiClient.kt
package com.example.samir.apiclientapp

import io.reactivex.Observable
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*

interface ArticlesApiClient {

    /* Get list of articles */
    @GET("posts")
    fun getArticles(): Observable<List<Article>>

    /* Get one article by it's id */
    @GET("posts/{id}")
    fun getArticle(@Path("id") id: Int): Observable<Article>

    /* Add new article */
    @Headers("Content-Type: application/json;charset=utf-8")
    @POST("posts")
    fun addArticle(@Body article: Article): Observable<Article>

    companion object {

        fun create(): ArticlesApiClient {

            val retrofit = Retrofit.Builder()
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl("https://jsonplaceholder.typicode.com/")
                    .build()

            return retrofit.create(ArticlesApiClient::class.java)

        }
    }

}

Most of this will be familiar to you if you used retrofit with Java except the companion object which is Kotlin’s feature. The companion object is a singleton object. The methods in the companion object are analogous to (public) static methods, it is an actual object instead of just a loose set of functions and fields within a specific scope. This allows interface implementation, assignment to variables, etc. In this case we will use it to define function which will return ArticlesApiClient instance.

Implementation

Our ArticleApiClient is ready and we can consume API data. To test our little client app we will add three functions in our MainActivity.kt file. Each function will use RXJava to subscribe to Observables and log response so we can see it in our Logcat output.

MainActivity.kt
package com.example.samir.apiclientapp

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers

class MainActivity : AppCompatActivity() {

    val client by lazy {
        ArticlesApiClient.create()
    }

    var disposable: Disposable? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Uncomment to show list of articles in Logcat
        //showArticles()

        // Uncomment to show article with id=1 in Logcat
        //showArticle(1)

        // Test post request and add new article
        val article = Article(1, 101, "Test Article", "Have fun posting")
        postArticle(article)

    }

    // GET List of Articles
    private fun showArticles() {

        disposable = client.getArticles()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        { result -> Log.v("ARTICLES", "" + result) },
                        { error -> Log.e("ERROR", error.message) }
                        )

    }

    // GET Article by id
    private fun showArticle(id: Int) {

        disposable = client.getArticle(id)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        { result -> Log.v("ARTICLE ID ${id}: ", "" + result) },
                        { error -> Log.e("ERROR", error.message) }
                )

    }

    // POST new Article
    private fun postArticle(article: Article) {

        disposable = client.addArticle(article)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        { result -> Log.v("POSTED ARTICLE", "" + article ) },
                        { error -> Log.e("ERROR", error.message ) }
                )
    }

    override fun onPause() {
        super.onPause()
        disposable?.dispose()
    }

}

Please check full app code on github https://github.com/SKaDiZZ/apiclient
Now when you have your data it’s easy to output it in RecyclerView or wherever you need it. I had limited free time to write this article but I hope you guys will find it useful in your work or learning. Kotlin is new amazing kid in neighborhood and you should use it.

Please check part 2 of this tutorial

Output data in RecyclerView using Kotlin

Recommended reading

Share with your friends