Coil and Ktor in Kotlin Multiplatform Compose project
Tags: kotlin, multiplatform, compose, multiplatformcompose
Published: 2024-06-14 09:22:50

Many people are trying but having a hard time adding Coil in a Multiplatform compose project that works on both JVM/Android/iOS and WASM. 

Now we have to use Ktor since okHttp is android only for now.
We will be using:
- Coil 3.0 https://coil-kt.github.io/coil/
- Ktor 3.0 with wasm support

After spending half a day making it work I decide to share it for others.

I will be using the latest versions that support wasm as of 14.06.2024, for later readers and experimenting you might want to upgrade the versions.

## 1) Libraries and versions

In short first you need to add **ktor**. In your libs.versions.toml add

```
[versions]

ktor = "3.0.0-wasm2"

```

```
[libraries]
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-java = { group = "io.ktor", name = "ktor-client-java", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" }
ktor-client-serialization = { group = "io.ktor", name = "ktor-client-serialization", version.ref = "ktor" }
ktor-client-content-negotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" }
ktor-client-json = { group = "io.ktor", name = "ktor-client-json", version.ref = "ktor" }
ktor-client-logging = { group = "io.ktor", name = "ktor-client-logging", version.ref = "ktor" }
```

now you can also create a bundle since this makes your `build.gradle.kts` far smaller so just add the bundle as well

```
[bundles]
ktor-common = ["ktor-client-core", "ktor-client-json", "ktor-client-logging", "ktor-client-serialization", "ktor-client-content-negotiation", "ktor-serialization-kotlinx-json"]
```

Now you can stop here if you only need to use ktor in your multiplatform compose projects, in such case scroll down to point **2 updating your build script**, however if you want to use coil you need 4 extra dependancies

Add this version
```
[versions]
coilComposeCore = "3.0.0-alpha06"
```

and this 4 libraries
```
[libraries]

coil = { module = "io.coil-kt.coil3:coil", version.ref = "coilComposeCore" }
coil-compose-core = { module = "io.coil-kt.coil3:coil-compose-core", version.ref = "coilComposeCore" }
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coilComposeCore" }
coil-network-ktor = { module = "io.coil-kt.coil3:coil-network-ktor", version.ref = "coilComposeCore" }
```


Now you are good to go to your `build.gradle.kts` file

## updating your build script

Open your `build.gradle.kts` 

add ` maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental")` to your repositories so you can download the ktor wasm version

```kotlin
allprojects {
    repositories {
        google()
        mavenCentral()
maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental")
    }
}
```
then in commonMain.dependancies add

```kotlin
commonMain.dependencies {
....
            implementation(libs.bundles.ktor.common)
            implementation(libs.coil.compose.core)
            implementation(libs.coil.compose)
            implementation(libs.coil)
            implementation(libs.coil.network.ktor)
```

in Android dependancies add
```kotlin
        androidMain.dependencies {
....
  implementation(libs.ktor.client.okhttp)
        }
```

in iOS/Apple dependancies add
```kotlin
      iosMain.dependencies {
            implementation(libs.ktor.client.darwin)
        }
```
in JVM dependancies add
```kotlin
 jvmMain.dependencies {
            ....
            implementation(libs.ktor.client.java)
        }
```

Thats it more or less for dependancies.

NOTE you might need also kotlinx.serialization, if you have it ignroe this and scroll to **3 how to verify coil is working.**
 so in libs add 
```
[versions]

kotlinx-serialization = "1.6.3"

[libraries]

kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
```

then in your gradle kts file
```kotlin
plugins {
....
    alias(libs.plugins.kotlinx.serialization)
}
```

and only in 
```kotlin
commonMain.dependencies {
....
implementation(libs.kotlinx.serialization.json)
```

Thats it you are good to use Ktor in your multiplatform compose project or Ktor + Coil .

## How to verify coil is working ?

Example how to use coil can be found over the internet but in short in your App.kt in commonMain add this function

```kotlin
fun getAsyncImageLoader(context: PlatformContext)=
    ImageLoader.Builder(context).crossfade(true).logger(DebugLogger()).build()
```

Then in your App function just add this
```kotlin
@Composable
internal fun App() = AppTheme() {

    setSingletonImageLoaderFactory { context ->
        getAsyncImageLoader(context)
    }
.... rest code
```

and then you can use Coil.. for example like this :
```kotlin
                            AsyncImage(
                                model = "https://1.bp.blogspot.com/-m4g5Q9WZuLw/YO7FxYJsnsI/AAAAAAAA6fs/nyDiNA_6EHMrPw3qRLJ7FcR1-MoC4rkZwCLcBGAsYHQ/s0/javabeer.jpg",
                                placeholder = painterResource(Res.drawable.ic_cyclone),
                                contentDescription = null,
                                contentScale = ContentScale.Crop,
                                modifier = Modifier.clip(CircleShape)
                            )

```

I hope this is helpful for someone ! And go enjoy coding with multiplatform compose, I hope I saved you the 4 hours I lost.

P.S. I use kotlin 2.0 and compose 1.6.11 and serialization 1.6.3