Make REST API request with Kotlin ktor client in android

Ktor is a framework to easily build connected applications, web applications, HTTP services, and mobile and browser applications. Modern connected applications need to be asynchronous to provide the best experience to users, and Kotlin coroutines provide awesome facilities to do it in an easy and straightforward way.

Ktor is a new framework for building asynchronous servers and clients. It’s 100% Kotlin and runs on Coroutines.

To learn more about kotlin, Please check

Beginning Android Development with Kotlin

Why Ktor for android?

Ktor uses coroutines for asynchronous programming to keep the code readable and clean. In addition to that, Ktor has many Kotlinx libraries to help developers with tasks like parsing the response.

Using a networking library that can be integrated into multiple platforms is a better solution than choosing platform-specific libraries. As JetBrains develop it, there will be more advanced features and long-term support.

Building the HTTP client

Ktor client provides you with an interface to make HTTP requests, however, it relies on an engine to perform its duties. For Android, you can work with one of the following engines:

CIO (Coroutine-based I/O)

Ktor has an interface to make HTTP requests that depend on the engine. Ktor provides a CIO (Coroutine-based I/O) to make it work.

Note: HTTP/2 is not supported.

//dependency
     implementation 'io.ktor:ktor-client-cio:1.2.2'

        // creating CIO client
        val client = HttpClient(CIO) {
            ....
        }

Ktor Setup On Android

Android which uses the usual HttpURLConnection and ThreadPool to execute requests.

//dependency
        implementation "io.ktor:ktor-client-android:1.2.2"

        // creating Android client
        val client = HttpClient(Android) {
            ....
        }

OkHttp Setup

OkHttp which depends on Square’s OkHttp client.

//dependency
        implementation "io.ktor:ktor-client-okhttp:1.2.2"

        // creating OkHttp client
        val client = HttpClient(OkHttp) {
            ....
        }

Configuring the client

We have to install a specific feature and optionally configure it.

Request type

Ktor HTTP client allows you to configure GET, and POST request types. let’s see how to configure the request types.

GET

//GET request - Method 1
        val response = client.get<List<String>>("requestUrl")

        //GET request - Method 2
        val response = client.request<List<String>>("requestUrl") {
            method = HttpMethod.Get
        }

POST

//POST request - Method 1
        val response = client.post<List<String>>("requestUrl")

        //POST request - Method 2
        val response = client.request<List<String>>("requestUrl") {
            method = HttpMethod.Post
        }

Headers

We need to install DefaultRequest in the Ktor HTTP client to set the header for the HTTP client.

val client = HttpClient(CIO) {
            install(DefaultRequest) {
                headers.append("Accept","application/json")
                headers.append("Authorization","Bearer token")
            }
        }

Also, we can configure headers directly while requesting.

val response =  client.get {
            url("requestUrl")
            header("Accept","application/json")
            header("Authorization","Bearer token")
        }

Serializers

Processes the request and the response payload as JSON, serializing and de-serializing them using a specific Json-Serializer.

Ktor supports libraries like Gson, Jackson, or Kotlinx.Serialization via their respective clients.

Gson

//dependency
        implementation 'io.ktor:ktor-client-gson:1.2.2'

        //configuring GSON serializer
        val client = HttpClient(CIO) {
            install(JsonFeature) {
                serializer = GsonSerializer()
            }
        }

Jackson

//dependency
        implementation 'io.ktor:ktor-client-jackson:1.2.2'

        //configuring Jackson serializer
        val client = HttpClient(CIO) {
            install(JsonFeature) {
                serializer = JacksonSerializer()
            }
        }

Kotlinx.Serialization

//dependency
        implementation "io.ktor:ktor-client-serialization-jvm:1.2.2"

        //configuring KotlinxSerializer
        val client = HttpClient(CIO) {
            install(JsonFeature) {
                serializer = KotlinxSerializer()
            }
        }

Executing Ktor Request With Coroutines

To make a GET request, we have to use the get inline function on Ktor’s HttpClient with a response data class and request URL.

val response = client.post<List<String>>("requestUrl")

get is also a suspend function, so it’ll take care of executing the request on the I/O thread.

With coroutines, we can execute asynchronous requests sequentially.

We need to wrap the request with a try/catch block to capture errors and exceptions.

@KtorExperimentalAPI
        suspend fun fetchAllMovies() {
            try {
                val response = client.post<List<String>>("requestUrl")
            } catch (e : java.lang.Exception) {
                 //handle Exception
                if (e.message.isNotEmpty()) {
                    // known exception
                }else{
                    //unknown exception
                }
            }
        }

Now, we are done with HTTP client creation and configuration. Let’s create a sample using Ktor.

Ktor Android Example

I am going to create a sample application to fetch a list of movies from API using Ktor and a list in recyclerview.

Adding dependencies

First, we need to add the dependencies for Ktor and recyclerview.

//http client
        implementation 'io.ktor:ktor-client-cio:1.2.2'
        //gson 
        implementation 'io.ktor:ktor-client-gson:1.2.2'
        //coroutines
        implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
        implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
        //material design 
        implementation 'com.google.android.material:material:1.2.1'
        //glide
        implementation 'com.github.bumptech.glide:glide:4.11.0'

Setup Recyclerview

To set up recyclerview check out my other post on recyclerview.

Recyclerview Android Example [Beginners]

Also, I have used Glide to load the image from API.

Glide Library — Image Loading Library For Android

Used ShapeableImageView to make the images in a circle shape.

ShapeableImageView — Material Components For Android

my adapter layout:

recyclerview adapter design

set the adapter into recyclerview.

val adapter = RecyclerviewAdapter() 
    recyclerview.adapter = adapter

Make HTTP Request

To make a request first, we need to create an HTTP client.

MovieApi.kt

class MovieApi {

        //Request
        private val client = HttpClient(CIO) {
            install(DefaultRequest) {
                headers.append("Content-Type", "application/json")
            }

            install(JsonFeature) {
                serializer = GsonSerializer()
            }
        }

        @KtorExperimentalAPI
        suspend fun fetchAllMovies(): List<Movie> {
            try {
                return client.get {
                    url("https://www.howtodoandroid.com/movielist.json")
                }
            } catch (e : java.lang.Exception) {
                return emptyList()
            }
        }
    }

Now make the Network call using httpClient in Dispatchers.IO and set the response into the recyclerview in Dispatchers.Main.

MainActivity.kt

class MainActivity : AppCompatActivity() {

       lateinit var adapter: RecyclerviewAdapter

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            adapter = RecyclerviewAdapter()
            recyclerview.adapter = adapter
            fetchAllMovies()
        }

        @KtorExperimentalAPI
        private fun fetchAllMovies()  {

            CoroutineScope(Dispatchers.IO).launch {
                val movieApi = MovieApi()
                val response = movieApi.fetchAllMovies()
                withContext(Dispatchers.Main) {
                    adapter.setMovieItems(response)
                }
            }
        }
    }

That’s it. we have successfully fetched the data from API and set it into recyclerview.

you can download this example on Github.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *


Latest Posts