InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
8.98k stars 712 forks source link

Declaring koin modules in common module for iOS in Compose Multiplatform #1974

Closed muazkadan closed 2 weeks ago

muazkadan commented 2 weeks ago

Hello,

I'm having a problem with my Compose Multiplatform project (Android & iOS) where injected objects are acting different on each platform

To demonstrate the issue, I tried the sample code below:

I'm using koin-bom 4.0.0-RC2 with koin-core, koin-android, koin-compose and koin-compose-viewmodel Kotlin 2.0.20, compose-plugin 1.7.0-beta02, Compose-navigation 2.8.0-alpha10 and androidx-lifecycle 2.8.2

import androidx.compose.runtime.*
import org.koin.compose.KoinApplication
import org.koin.compose.koinInject
import org.koin.dsl.koinApplication
import org.koin.dsl.module

class Person(val name: String)

val personModule = module {
    single { Person("Muaz") }
}

@Composable
fun App() {
    KoinApplication(application = {
        koinApplication {
            modules(personModule)
        }
    }) {
        val person = koinInject<Person>()
        println("Person: ${person.hashCode()}")
    }
}

On Android the code printed Person: 2409473

While on iOS I got:

Person: 2409473
Person: 2409473

No idea why the code got called twice here

The weird thing happens when I add a Scaffold to the Compose hierarchy like this:

@Composable
fun App() {
    KoinApplication(application = {
        koinApplication {
            modules(personModule)
        }
    }) {
        val person = koinInject<Person>()
        println("Person: ${person.hashCode()}")
        Scaffold {
            val person2 = koinInject<Person>()
            println("Person2: ${person2.hashCode()}")
        }
    }
}

on android I got:

Person: 55430932
Person2: 55430932

While on iOS I got:

Person: 120607280
Person: 120607280
Person2: 120624896
Person2: 120624896

Not sure if this is a problem with Koin or Compose Multiplatform And not sure if initializing koin and declaring modules in the shared code is true

In my project I'm using DataStore Preferences similarly as above which is causing the iOS app to crash as I can't create multiple instances of the same data store

kotlin.IllegalStateException: There are multiple DataStores active for the same file: xxxx

Any help would be greatly appreciated

arnaudgiuliani commented 2 weeks ago

was it working in RC1 or previous?

muazkadan commented 2 weeks ago

Yes, the code below with 4.0.0-RC1

@Composable
fun App() {
    KoinApplication(application = {
        modules(personModule)
    }) {
        val person = koinInject<Person>()
        println("Person: ${person.hashCode()}")
        Scaffold {
            val person2 = koinInject<Person>()
            println("Person2: ${person2.hashCode()}")
        }
    }
}

prints on iOS:

Person: 144249656
Person: 144249656
Person2: 144249656
arnaudgiuliani commented 2 weeks ago

updated in 7bd030cd9c38478838a82b75904d3d5df5752e96 Reopen if on next release the issue come back 👍