Ktor – Networking Client For Android

Ktor Networking client

Ktor is a framework to easily build connected applications — web applications, HTTP services, 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

koin | Dependency Injection In Android

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 depends 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) {
        ....
    }

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

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, POST request types. lets 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 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 on 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. Lets create sample using Ktor.

Ktor Android Example

I am going to create sample application to fetch list of movies from API using Ktor and 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 setup recyclerview checkout my another 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 circle shape.

ShapeableImageView — Material Components For Android

my adapter layout:

set the adapter into recyclerview.

val adapter = RecyclerviewAdapter() 
recyclerview.adapter = adapter

Make HTTP Request

To make a request first, we need to create 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://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 thread.

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 in Github.

Leave a Reply

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