Compose Multiplatform项目中Room数据库的Koin NoDefinitionFoundException问题
Compose Multiplatform + Koin + Room 依赖注入异常排查
问题背景
我正在开发一个Compose Multiplatform项目,采用Koin做依赖注入、Voyager实现导航、Room管理本地数据库。在尝试通过RoomDatabase.Builder提供ForgoDatabase实例时,触发了NoDefinitionFoundException。这是我第一次接触Compose Multiplatform,已经参考过各库官方文档和GitHub上的实现案例,但始终找不到问题根源。
Koin插件警告

项目配置文件
build.gradle.kts
import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.androidApplication) alias(libs.plugins.composeMultiplatform) alias(libs.plugins.composeCompiler) alias(libs.plugins.ksp.plugin) alias(libs.plugins.room.gradle.plugin) } kotlin { androidTarget { compilerOptions { jvmTarget.set(JvmTarget.JVM_11) } } listOf( iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { iosTarget -> iosTarget.binaries.framework { baseName = "ComposeApp" isStatic = true linkerOpts.add("-lsqlite3") } } room { schemaDirectory("$projectDir/schemas") } sourceSets { commonTest.dependencies { implementation(libs.kotlin.test) } androidMain.dependencies { implementation(compose.preview) implementation(libs.androidx.activity.compose) implementation(libs.koin.android) implementation(libs.koin.androidx.compose) } commonMain.dependencies { implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material3) implementation(compose.ui) implementation(compose.components.resources) implementation(compose.components.uiToolingPreview) implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.kotlinx.date.time) implementation(libs.kotlinx.coroutines) // Voyager implementation(libs.bundles.voyager) // Koin implementation(libs.koin.compose) implementation(libs.koin.viewmodel) api(libs.koin.core) // Room implementation(libs.room.runtime) implementation(libs.sqlite) } all { languageSettings.optIn("kotlin.ExperimentalMultiplatform") languageSettings.optIn("kotlin.RequiresOptIn") } } compilerOptions { freeCompilerArgs.add("-Xexpect-actual-classes") } } android { namespace = "com.feeltheboard.forgo" compileSdk = libs.versions.android.compileSdk.get().toInt() sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") sourceSets["main"].res.srcDirs("src/androidMain/res") sourceSets["main"].resources.srcDirs("src/commonMain/composeResources") defaultConfig { applicationId = "com.feeltheboard.forgo" minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt() versionCode = 2 versionName = "1.0.2" } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } buildTypes { getByName("release") { isMinifyEnabled = false } } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } } dependencies { debugImplementation(compose.uiTooling) add("kspCommonMainMetadata", libs.room.ksp) add("kspAndroid", libs.room.ksp) add("kspIosSimulatorArm64", libs.room.ksp) add("kspIosX64", libs.room.ksp) add("kspIosArm64", libs.room.ksp) }
依赖版本(libs.versions.toml)
[versions] agp = "8.9.0" android-compileSdk = "35" android-minSdk = "24" android-targetSdk = "35" androidx-activityCompose = "1.10.1" androidx-appcompat = "1.7.0" androidx-constraintlayout = "2.2.1" androidx-core-ktx = "1.15.0" androidx-espresso-core = "3.6.1" androidx-lifecycle = "2.8.4" androidx-material = "1.12.0" androidx-test-junit = "1.2.1" compose-multiplatform = "1.7.0" kotlinx-coroutines="1.8.1" kotlinx-date-time="0.6.2" junit = "4.13.2" koin = "4.0.2" kotlin = "2.1.0" ksp = "2.1.0-1.0.29" room = "2.7.0-rc02" sqlite = "2.5.0-alpha01" voyager = "1.1.0-beta02"
核心代码实现
CommonMain 中的 SharedModule
expect val platformModule: Module val sharedModule = module { single { getRoomDatabase(get()) } single<ForgoRepository> { ForgoRepositoryImpl(get()) } factory { HomeViewModel(get()) } factory { TaskViewModel(get()) } } fun appModules() = listOf(sharedModule, platformModule)
CommonMain 中的 Room 数据库定义
@Database(entities = [Task::class], version = 5, exportSchema = true) @ConstructedBy(ForgoDatabaseConstructor::class) abstract class ForgoDatabase : RoomDatabase() { abstract fun taskDao(): TaskDao } @Suppress("NO_ACTUAL_FOR_EXPECT") expect object ForgoDatabaseConstructor : RoomDatabaseConstructor<ForgoDatabase> { override fun initialize(): ForgoDatabase } fun getRoomDatabase( builder: RoomDatabase.Builder<ForgoDatabase> ): ForgoDatabase { return builder .fallbackToDestructiveMigrationOnDowngrade(dropAllTables = true) .setDriver(BundledSQLiteDriver()) .setQueryCoroutineContext(Dispatchers.IO) .build() }
Android 端实现(androidMain)
fun getDatabaseBuilder( ctx: Context ): RoomDatabase.Builder<ForgoDatabase> { val appContext = ctx.applicationContext val dbFile = appContext.getDatabasePath("task.db") return Room.databaseBuilder<ForgoDatabase>( context = appContext, name = dbFile.absolutePath ) } actual val platformModule: Module = module { single { getDatabaseBuilder(ctx = get()) } } class MainApplication : Application() { override fun onCreate() { super.onCreate() initializeKoin { androidContext(this@MainApplication) } } } class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { App() } } }
内容的提问来源于stack exchange,提问作者Rafael Moreira
相关产品推荐
相关产品推荐

