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:
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.
Leave a Reply