Retrofit is every Android developer’s favourite library for making API calls and there is no doubt about it.
Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.
Then what is Ktor Client and why do we even need it when we already have an awesome library named Retrofit to do the same in minimal code? Let’s try to find answers of all these questions. In this article I will not only tell you why you should give Ktor-Client a shot, but also show you how to implement REST APIs in Ktor Clients.
What and Why?
Let’s check out first what Ktor-Client is.
Ktor includes a multiplatform asynchronous HTTP client, which allows you to make requests and handle responses, extend its functionality with plugins (formerly known as features), such as authentication, JSON serialization, and so on.
In simple words, Ktor-Client, just like Retrofit can be used to make API calls, with functionalities such as adding headers, choosing from various serialization libraries and much more.
Now the next question arises, why?? Why do we need a new networking library when we already have Retrofit???
Retrofit is great when we want to use a networking library for our Android native apps. But how about we want to use something similar in other platforms as well? When I say other platforms, I bet Kotlin Multiplatform comes to your mind as one of the options as well. Kotlin Multiplatform is trending especially after Google launched a stable version of Jetpack Compose last year.
Ktor-Client can not only be used for networking in native Android specific applications, but also when we are working on multi-platform Kotlin projects, unlike Retrofit which is platform-specific. This knowledge of using Ktor-Client will not only help in developing for Android, but also developing multiplatform projects. Besides this, knowledge and familiarity with Ktor will also help us developing APIs as discussed in my previous article here
Ktor uses coroutines internally for asynchronous programming which makes our code very clean and minimal just like coroutines did with suspend functions. Moreover it is as easy to add headers, serialization, logging etc in our app, as it is with Retrofit.
With the popularity of Kotlin Multiplatform and it being adopted by various companies, especially startups, I am positive that it has a chance of replacing Retrofit in coming years. It is developed by JetBrains, so they will keep adding more and more features in coming time.
Enough talking and theory!! Let’s now jump straightaway to the coding part. We will be adding popular unsplash API in our project with authentication to our header. I will be using the MVVM architecture and skipping the UI and the ViewModel part as it is out of scope of this article. However, if you want to check the complete working code on GitHub, it can be found here.
How?
First of all, just like we do it with Retrofit, we will add an API Service interface, which will consist of function declarations. We will use only one API in our app, which will fetch the list of images from our app. ImageResponse here is the response data class.
That’s it?? It’s same as Retrofit!! Where are the queries? Where is the url?? Where are the headers???
Let’s find out the answer and I will also discuss how these both differ internally the way they work.
If I were to use Retrofit, the syntax would be something similar to -:
Retrofit uses reflections internally which creates these classes and objects required for http connection during runtime without knowing the names of the interfaces, fields, methods at compile time. If we dig more deeper, OkHttp is used by Retrofit which helps to communicate with sockets.
Let’s see how it goes in Ktor-Client and where do we specify our base url, endpoint, queries etc.
Ktor-Client does not use the reflection APIs or OkHttp, instead it uses an asynchronous client to perform HTTP requests named HttpClient which uses HttpResponsePipeline and HttpRequestPipeline, former to process all the responses sent by the server and latter for processing all the requests sent by the client.
Http.get specifies that we are making a GET request to our API, we can use Http.post to make a POST request. The lambda function is HttpRequestBuilder where we have specified our header, which in our case is Authorization and our url. Just to clarify HttpHeaders.Authorization is nothing but a string with value “Authorization” provided inbuilt by Ktor. In case you’re curious about other use cases of HttpRequestBuilder, we can specify request method, request body etc in it.
All looks till now good except one thing, where do we specify serialization options/libraries and logging options just like we did with in our RetrofitBuilder class? How does KtorClient serializes/deserializes the request/response? Don’t worry I got you covered.
Let’s get back to our ImagesService class and modify it to meet these requirements.
We have already discussed about HttpClient. “Android” here is an implementation of HttpClientEngineFactory interface. Let’s keep that out of scope of this article. Let’s discuss the lambda function. This is a HttpClientConfig class which in turn is a mutable configuration used by HttpClient. Let’s check out some code of HttpClient by Ktor Library to understand the role of HttpClientConfig class better.
To make it clear, anything we add in the block of HttpClient class, just like we added our Logging and GsonConvertor libraries for logging and serialization/deserialization respectively, will be added to HttpClient and used while executing. This is just like adding up some default libraries like HttpSend, HttpRedirect etc with our custom block we specified with our ImageService interface.
Now the only thing left is how to call this from our repository??? Let’s check the code for that as well.
We use a coroutine to call our method from ImagesService as this is an asynchronous operation. That’s it! Now we can use this method in our ViewModel and update UI accordingly. As mentioned earlier, I will keep that out of scope of this article, you can visit the Github repo with the complete working project here
Are you loving it already????? Yes, me too!! Let’s implement it in our projects already then?? Is it alright to completely replace Retrofit in our projects and replace it with KtorClient??? Let’s find an answer to this.
When?
As discussed earlier, Ktor-Client can not only be used for networking in native Android specific applications, but also when we are working on multi-platform Kotlin projects, unlike Retrofit which is platform-specific.
But it is worth to notice that Ktor is in very early stages and not used already in the industry at least as a replacement of Retrofit. It is good to use a new library to “experiment” or even use it in production for some easy-use cases. But there is limited community/published articles/documentation material available for KtorClient as compared to massive material and support available for Retrofit. So if you get stuck in a complex use case, it can be a hard time if using KtorClient.
What I feel is, it is completely fine to learn, experiment and implement KtorClient in Kotlin multiplatform projects which are pretty new and mostly used by startups, but it may not be worth replacing Retrofit with KtorClient in native production apps at this point of time. I am positive that more features, community and support will be available for Ktor and KtorClient in coming future very soon. But for now, I will go with retrofit for native android apps and ktor-client for multiplatform.
Ps-: All this is based on my personal opinion and preferences, things may change with time and opinions may vary from person to person. Do let me know in the comments your opinions and experience with Ktor-Client. The code for the project can be found here. Thanks for taking out the time to read this article.