Blog Infos
Author
Published
Topics
, , , ,
Published
Photo by Hardik Sharma on Unsplash
Takeaway from this article

In this article, you’ll learn why we might need to migrate from Retrofit to Ktor and KAPT to KSP. By the end of this article, you will be able to remove Retrofit and KAPT from the project safely.

. . .

Introduction

This is part 2 in the series of migrations from the Android project to the kotlin multiplatform project. In Part 1, we discussed the KMP technology and the tech stack used in migrating applications to KMP. Then as a first step, we started with dependency injection migration from Hilt to Koin. The following is the link to the article in case you missed it.

In this part of the series, we’ll focus on migrating two main things:

  1. Android network library Retrofit to purely Kotlin-based Ktor.
  2. KAPT annotation processor to generate the code to KSP (Kotlin Symbol Processing).

Retrofit is a stable and very popular library in the Android world, but the lack of KMP support leaves me with no choice but to migrate. Ktor is the obvious choice to migrate as it’s built purely with Kotlin and is being maintained by Google. Ktor is more than just another client library for networking, to learn more about it read the following in-depth articles:

  1. How to Use Ktor in Your Android App
  2. Ktor in Server-Side Development: The Basics

Kapt (Kotlin Annotation Processing Tool) enables Java annotation processors usage in Kotlin projects, even when the processors aren’t designed for Kotlin. KSP (Kotlin Symbol Processing) offers a Kotlin-centric alternative to Kapt. Unlike Kapt, KSP directly analyzes Kotlin code, making it up to twice as fast. Additionally, it has a deeper understanding of Kotlin’s language features.

. . .

Retrofit to Ktor Migration
Integration

To integrate ktor into the project add the following lines under the dependencies node in the app module and other modules where you might have to make the network calls.

// Ktor
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
implementation("io.ktor:ktor-client-core:2.3.12")
// CIO - for JVM and Android
implementation("io.ktor:ktor-client-cio:2.3.12")
implementation("io.ktor:ktor-client-content-negotiation:2.3.12")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.12")

Then add the following line under the plugins section in the project-level gradle file.

id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.23' apply false

 

Now add the following lines in app/proguard-rules.pro to make sure Ktor works as expected in release builds even with obfuscation.

# Ktor
-keep class io.ktor.** { *; }
-keep class kotlinx.coroutines.** { *; }
-dontwarn kotlinx.atomicfu.**
-dontwarn io.netty.**
-dontwarn com.typesafe.**
-dontwarn org.slf4j.**

 

Then remove all the Retrofit-related dependencies and hit the sync now button.

DI Migration

Now we need to update the Koin network and data source modules, replacing the Retrofit with Ktor. Let’s start with the network module, The following is the Retrofit setup of the network module.

val networkModule = module {
    single<Gson> { GsonFactory.create() }
    single<Converter.Factory> { GsonConverterFactory.create(get()) }
    single<OkHttpClient> {
        OkHttpClientFactory.create()
    }
    single<Retrofit> {
        RetrofitFactory.create(
            okHttpClient = get(),
            converterFactory = get(),
        )
    }
}

 

After migration to Ktor, it looks as follows:

val networkModule = module {
    single<Json> {
        Json {
            ignoreUnknownKeys = true
            isLenient = true
            prettyPrint = true
            encodeDefaults = true
        }
    }

    single<HttpClient> {
        HttpClient(CIO) {
            install(ContentNegotiation) {
                get<Json>()
            }
        }
    }
}

 

Now we need to replace the retrofit inject with the Ktor client, as I’ve a single API in the application, I’m replacing the retrofit service interface with Kotr client and requesting with the client directly. But the real-time use of Ktor will be much more complicated with multiple routes and header configuration for which please refer to this article.

Before:

class WizardRemoteDataSource constructor(
    private val api: RetrofitServiceApi,
): WizardDataSource

 

After:

class WizardRemoteDataSource constructor(
    private val httpClient: HttpClient,
): WizardDataSource

 

That’s all, now the project network module is compatible with kotlin multiplatform.

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

No results found.

Jobs

No results found.

KAPT to KSP Migration

Before migrating your code to KSP, there are a few important considerations to keep in mind. Since KSP is relatively new, some libraries may not yet support it. However, there’s no need to worry — you can run KSP and Kapt side by side in your project.

It’s worth noting that Kapt is now in maintenance mode, so it’s a good idea to encourage your library providers to upgrade to KSP as soon as possible. Fortunately, many popular libraries like Dagger, Moshi, Room, and others already support KSP. To know more about supported libraries refer to this link.

Now let’s start the migration, I prefer to increase the Kotlin version before integrating KSP, in the project-level gradle upgrade Kotlin plugin.

// Before
    id 'org.jetbrains.kotlin.android' version '1.8.10' apply false

// After

    id 'org.jetbrains.kotlin.android' version '2.0.0' apply false

 

Then move to the module-level gradle files starting with the app module, remove the kapt and add ksp plugin, have a look:

Then remove all the kapt references like the following from the gradle:

As a final step replace all the kapt dependency integration to ksp as shown below:

Now hit the “sync now” button and then rebuild the project to complete the code generation.

The following are some common issues to look out for stated in the Android Official Documentation:

  • Some libraries don’t support the same set of features with kapt and KSP. If your code breaks after migrating, check the library’s documentation.
  • KSP has more accurate Kotlin-type information than kapt (for example, about nullability), which means that KSP processors can be more precise about type requirements. This might require some fixes in your source code as well, in addition to updating your build files.
  • If you were previously passing in arguments to the annotation processor, you’ll likely need to pass in those arguments to KSP now. Note that the format of the arguments might differ between kapt and KSP. See the KSP documentation and consult the documentation of the library you’re using to learn more.

. . .

That is all for now, hope you learned something useful, thanks for reading.

You can find me on MediumTwitterQuora and LinkedIn.

This article is previously published on proandroiddev.com.

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
This tutorial is the second part of the series. It’ll be focussed on developing…
READ MORE
blog
A few weeks ago I started with a simple question — how to work…
READ MORE
blog
With JCenter sunsetted, distributing public Kotlin Multiplatform libraries now often relies on Maven Central…
READ MORE
blog
If you seek to unlock the potential of a powerful trifecta — Ktor, PostgreSQL,…
READ MORE
Menu