KMP中如何通过Koin注入Android上下文到SqlDelight Driver?
解决KMP中Koin注入Android上下文给SqlDelight Driver的问题
核心调整思路
问题根源在于你在commonMain中直接启动了Koin,但Android平台需要的Context是平台专属依赖,无法在common层提供。正确的做法是将Koin的启动逻辑下放给各平台,common层只负责定义通用模块,平台层补充专属依赖后再启动Koin。
具体实现步骤
1. 修改commonMain的Koin配置
移除common中的startKoin调用,只保留模块定义和通用模块集合的提供方法:
// commonMain expect val dbModule: Module val repoModule = module { single<DbRepository> { DbRepository(get<SqlDriver>()) } } // 提供通用模块集合,供各平台调用 fun getCommonKoinModules() = listOf(dbModule, repoModule)
2. 实现Android端的dbModule并启动Koin
在AndroidMain中实现dbModule,依赖Context创建AndroidSqliteDriver,再在Application中启动Koin并传入上下文:
AndroidMain的dbModule实现:
// androidMain actual val dbModule: Module = module { single<SqlDriver> { AndroidSqliteDriver( schema = YourDatabase.Schema, // 替换为你的SqlDelight数据库Schema context = get<Context>(), name = "your_database_name.db" ) } }
Android Application类中的Koin初始化:
class MyApp : Application() { override fun onCreate() { super.onCreate() startKoin { // 传入Android上下文 androidContext(this@MyApp) // 加载common层的通用模块 modules(getCommonKoinModules()) } } }
3. 其他平台适配(示例)
iOS端可在iosMain中实现dbModule,使用NativeSqliteDriver:
// iosMain actual val dbModule: Module = module { single<SqlDriver> { NativeSqliteDriver(YourDatabase.Schema, "your_database_name.db") } }
之后在iOS启动代码中调用startKoin加载通用模块即可。
之前尝试失败的原因
- 尝试1:commonMain已启动Koin,Android端重复调用
startKoin触发KoinAppAlreadyStartedException。 - 尝试2:
koinApplication { ... }仅创建Koin实例未启动,且未关联已有实例,导致上下文无法被获取。 - 尝试3:加载上下文模块的时机太晚,common中启动的Koin初始化
dbModule时,Context还未注入,触发MissingAndroidContextException。
内容的提问来源于stack exchange,提问作者Saher Al-Sous
相关产品推荐
相关产品推荐

