掘金 人工智能 07月10日 10:38
MP - Realm (not just realm)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文探讨了在Kotlin Multiplatform (KMP)项目中,如何避免在JS平台中使用Realm数据库库。文章分析了在commonMain中使用implementation引入Realm库可能导致的问题,并推荐使用expect/actual机制,将Realm的依赖限制在Android和iOS平台。通过这种方式,可以确保JS平台不加载、不编译、不打包Realm库,从而避免编译和运行错误。文章还总结了正确的做法,并提供了构建配置结构,帮助开发者在KMP项目中安全、清晰地使用Realm。

🚫 在KMP项目中,如果在commonMain中直接使用`implementation("io.realm.kotlin:library-base")`,会导致所有平台(包括JS)尝试解析该依赖,由于Realm Kotlin不支持JS平台,会引发编译和运行错误。

✅ 推荐使用expect/actual分离平台实现。在commonMain中定义接口,在Android和iOS平台提供实际实现,而在JS平台不提供实现,或者提供空实现,以此来解决依赖问题。这样做使得Realm的依赖仅存在于Android/iOS的implementation中,JS无需引入Realm,从而避免错误。

❌ 方案二,即直接在commonMain中使用`implementation("io.realm.kotlin:library-base")`,无法通过jsMain禁用Realm的引入,因为Gradle会强制所有平台都解析该依赖,这无法满足在JS平台完全排除Realm的需求。

📌 最佳实践是,避免在commonMain中使用implementation引入Realm,转而采用expect/actual模式。同时,需要在jsMain中提供空实现或抛出异常,提示用户JS不支持Realm的操作,以确保项目的稳定性和可维护性。

参考多方文档-提供最佳的实践方案(为什么是它)

如果你采用的是 方案二(即在 commonMain 中直接用 implementation("io.realm.kotlin:library-base")),但又想在 jsMain完全禁止 Realm 的使用,你需要处理两个层面的问题:


🚫 问题概述

    commonMain 中使用 implementation("io.realm.kotlin:library-base"),意味着 所有平台(包括 JS)都会尝试解析该依赖

    但是 Realm Kotlin 不支持 JS 平台(只支持 JVM 和 Native),所以会导致:

      编译错误:JS 无法找到 Realm 的实现运行错误:JS 没有该库的支持,即使编译通过也会运行崩溃

✅ 最佳做法(禁止 JS 平台使用 Realm)

🔧 1. 使用 expect/actual 分离平台实现(推荐方式)

这是官方推荐的 KMP 设计方式 —— 接口放在 commonMain,平台实现放在 Android/iOS,JS 中不提供实现

sourceSets {  val commonMain by getting {    dependencies {      // 这样做jsMain还是会参与编译(正确的做法是注销掉,保持个平台持有(否则在编译时就会报错⚠️))      compileOnly("io.realm.kotlin:library-base:1.16.0")    }  }  val androidMain by getting {    dependencies {      implementation("io.realm.kotlin:library-sync:1.16.0")    }  }  val iosMain by getting {    dependencies {      implementation("io.realm.kotlin:library-base:1.16.0")    }  }}

那么问题来了(怎么设计统一调度呢????)

✅ 结构:

interface LocalResponse {    var id: String    var idToken: String    var refreshToken: String    var expiresIn: String    var localId: String    var email: String}expect fun createLocalResponse(): LocalResponseinterface LocalRealm {    suspend fun addUser(user: LocalResponse)    suspend fun deleteUserById(id: String)    suspend fun updateUserEmail(id: String, newEmail: String)    suspend fun getAllUsers(): List<LocalResponse>    suspend fun getUserById(id: String): LocalResponse?    suspend fun getUsersByName(email: String): List<LocalResponse>}expect fun createRealmManager(): LocalRealm

统一调度(直接使用:createLocalResponse ,createRealmManager) …………(^-^)

📌 这样 Realm 的依赖只存在于 android/ios 的 implementation 中,JS 不需要引入 Realm,安全且清晰。


❌ 2. 无法用编译选项跳过 JS 的 Realm 引入

如果你使用的是方案二,在 commonMain 直接使用 implementation("io.realm.kotlin:library-base"),那么 Gradle 会强制所有平台都解析这个依赖 —— 无法通过 jsMain 禁用。


🚫 方案二无法实现你要的目标

目标方案二能实现吗?
JS 完全排除 Realm(不加载、不编译、不打包)❌ 无法做到
Realm 仅存在于 Android / iOS 平台❌ 不可能完全排除
JS 编译时和运行时都会报错 不兼容⚠️ 高风险

✅ 正确做法总结

推荐做法说明
expect/actual 模式JS 平台避免依赖 Realm,同时为其他平台提供实际实现
仅在 androidMain/iosMain 引入 Realm避免 commonMainimplementation("realm")
JS 提供空实现或报错实现提示用户 JS 不支持 Realm 的操作

🔚 结论:

为了在 jsMain 中完全禁止 Realm 的使用,你必须避免在 commonMain 中使用 implementation 引入 Realm。👉 请改用 方案一(平台分离 + expect/actual)实现你的目标。


Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Kotlin Multiplatform Realm JS expect/actual
相关文章