Can I have an Android Context injected when using ...
# koin
d
Can I have an Android Context injected when using annotations?
I can do that when manually making a module by doing something like this
Copy code
actual val dbModule = module(createdAtStart = true) {
    single<AppDatabase> {
     DatabaseFactory(androidContext()).createRoomDatabase()
    }
}
Wish I could do that in the constructor
p
I suppose you could describe the Context in a module. And just inject normally in your dependency. Something like that:
Copy code
@Module
class ExpertModule {

    @Factory
    internal fun getContext(): Context {
        val koin = GlobalContext.get()
        return koin.get<Context>()
    }
}
I didn't tested. Can you check it @Deep Patel?
c
If you defined the androidContext in startKoin you shouldn't need to specify a new definition for it, it should just resolve with the generated definition iirc. The generated definition will use
context = get()
which according to the bottom of this page will resolve the closest context definition. If you look at the definition of androidContext(), you'll also see it just wraps a call to get() in a try catch to throw an exception with more useful messaging. Something like this should work ->
Copy code
@Single
fun providesAppDatabase(context: Context) : AppDatabase = DatabaseFactory(context).createRoomDatabase()
a
With Koin Annotations you just need to use a `Context`parameter to be used in your function. Just like Caleb said above 👍
d
Thanks for the responses ya’ll. I should have mentioned that I’m using koin with a multiplatform project. This makes this challenging because I don’t have a
context
since that’s an Android Specific thing, How can I setup my factory such that it’s provided with a
context
when created in
androidMain
, but not anywhere else it’s created?
I’m also using KSP with the annotation processor, I don’t see a generated android directory. Here’s my setup
Copy code
dependencies {
    // Koin
    add("kspCommonMainMetadata", libs.koin.ksp.compiler)
}
b
Yes you can. Add the koin android dependencies to just the android dependencies. made my initKoin function look like this
Copy code
fun initKoin(appDeclaration: KoinAppDeclaration? = null)
That way in my App class I can do this
Copy code
initKoin {
  androidContext(this@EventsApp)
}
iOS doesn’t care about a context so I just don’t pass anything in. Afterwards just invoke the method you passed in inside of the
startKoin
method
I actually just had this issue with annotations and the suggest way to do it is in this thread https://github.com/InsertKoinIO/koin-annotations/issues/105 The workaround I found was to create an expect factory in commonMain
Copy code
@Single
expect class AppDatabaseFactory {
  fun createAppDatebase: AppDatabase
}

@Single
fun provideAppDatabase(appDatabaseFactory: AppDatabaseFactory): AppDatabase = appDatabaseFactory.createAppDatabase()
In your androidMain you can do this
Copy code
@Single
actual class AppDatabaseFactory actual constructor() : KoinComponent {
  private val context: Application by inject()

  actual fun createAppDatabase(): AppDatebase = AppDatabase(context)
}
This solution works with koin annotations with the compile time checks on