0

I'm working in a small project trying to implement Kmm. The isse I got is with Koin, where I'm not able to inject DatabaseDriverFactory class in Android (where basically I need a Context).

This is my code:

// This code is in "commonMain"
interface MovieDataBase {
    suspend fun deleteAllPreviewMovies()
    suspend fun savePreviewMovies(input: List<PreviewMovieEntity>)
}

class DataBaseImpl(
    // This is the one class im not able to inyect
    databaseDriverFactory: DatabaseDriverFactory
) : MovieDataBase {
    private val database = AppDatabase.invoke(databaseDriverFactory.createDriver())
    private val queries = database.appDataBaseQueries

    override suspend fun deleteAllPreviewMovies() {
        withContext(Dispatchers.Default) { queries.deleteAllPreviewMovie() }
    }

    override suspend fun savePreviewMovies(input: List<PreviewMovieEntity>) {
        withContext(Dispatchers.Default) {
            input.map {
                queries.savePreviewMovies(
                    id = it.id,
                    posterPath = it.posterPath,
                    title = it.title
                )
            }
        }
    }
}

In the other modules:

// in commonMain

expect fun platformModule(): Module
...
val commonModule = module {
    platformModule()
    single<MovieDataBase> { DataBaseImpl(get()) }
    single { provideHttpClient() }
    single<MovieRemote> { MovieRemoteImpl(get()) }
    single<MovieApi> { MovieApiImpl(get(), get()) }
    factory { Dispatchers.Default }
}
...

// in iosMain
actual fun platformModule(): Module = module {
    single { DatabaseDriverFactory() }
    single { MainDispatcher() }
}
...
actual class DatabaseDriverFactory {
    actual fun createDriver(): SqlDriver {
        return NativeSqliteDriver(AppDatabase.Schema, "test.db")
    }
}
...

// in AndroidMain

// here im telling Koin to inyect the Context, but not providing a way (this could be the issue )

actual fun platformModule(): Module = module {
    single { DatabaseDriverFactory(get()) }
    single { MainDispatcher() }
}
...
actual class DatabaseDriverFactory(private val context: Context) {
    actual fun createDriver(): SqlDriver {
        return AndroidSqliteDriver(AppDatabase.Schema, context, "test.db")
    }
}
...

So, when I run the project without injecting this class, it works fine. I saw several post of this, but in those they directly instantiate the dataBase in Android/iOS, in my case I would like to inject this in the classes in my SharedModule.

What am I doing wrong?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Nicote Ool
  • 121
  • 8
  • What exactly is failing in your code? Are you getting any errors? – Phil Dukhov May 30 '22 at 02:55
  • Hi!, i just post below the error. – Nicote Ool May 30 '22 at 11:25
  • 1
    You should edit your question instead of posting it as an answer(please delete it). Also check out [Why should I not upload images of code/errors when asking a question?](https://meta.stackoverflow.com/a/285557/3585796) and replace images with [formatted](https://stackoverflow.com/help/formatting) text – Phil Dukhov May 30 '22 at 13:12
  • Each time I try to inject the DataBase, in Android Studio I get this error message: ``` 2022-05-30 08:31:38.950 3024-3024/com.example.basekmm_003.android D/onFailure: org.koin.core.error.InstanceCreationException: Could not create instance for [Singleton:'com.example.basekmm_003.MovieApi'] ```. If I not inject this, it seems to work just fine. – Nicote Ool May 30 '22 at 13:46

1 Answers1

0

I found out what was wrong. in my "Koin.kt" file y changed ->

fun initKoin(appDeclaration: KoinAppDeclaration = {}) = startKoin {
    appDeclaration()
    modules(
        commonModule
    )
}

to

fun initKoin(appDeclaration: KoinAppDeclaration = {}) = startKoin {
    appDeclaration()
    modules(
        platformModule(),
        commonModule
    )
}

I needed to put the "platformModule()" method in the same level at the "commonModule"

Nicote Ool
  • 121
  • 8