mcpField
K
kmp-boundaries

kmp-boundaries

github.com/rcosteira79开发165140 次安装6 周前更新
代码仓库

关于 kmp-boundaries

面向 Kotlin Multiplatform 的边界设计技能,说明如何划分共享代码与平台实现。重点涵盖按能力拆分接口、由 Activity 持有的 Android UI 绑定,以及 AGP 9 KMP 库的结构限制。

主要功能

  1. 01语义化的 commonMain 接口
  2. 02按能力划分平台边界
  3. 03Activity 作用域的 Android UI 绑定
  4. 04AGP 9 KMP 库限制
  5. 05iOS–Swift 互操作参考

适用场景

  1. 01设计平台能力的共享 API
  2. 02避免 Android 绑定中的 Activity 生命周期泄漏
  3. 03将 Android 应用迁移为 AGP 9 KMP 库
  4. 04为 Swift 调用准备 Kotlin API

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rcosteira79/android-skills --skill kmp-boundaries

安装后在 Claude Code 中输入/kmp-boundaries确认已加载。

附带文件references/ios-interop.md

详细介绍

Kotlin 多平台边界设计

KMP 边界的核心规则:

  • 让 commonMain 保持语义化 — 描述产品需要什么,而非 Android/iOS 的机制:使用 currentRegion(),而不是 currentRegionFromAndroidLocale(context)。
  • 按能力拆分 — 将 Clipboard、ShareSheet、Haptics、Biometrics 设计为独立接口,而不是一个包揽一切的 Platform 对象。
  • 让 actual 保持精简 — 它们负责转换,不负责决策;actual 内的业务 if/when 应放在 common 中,并用 fake 测试。
  • 只要需要 fake、DI、生命周期或运行时选择,就优先使用 common interface + 每个平台的绑定,而不是 expect class。
  • 仅当两个平台确实共享同一个 actual 时,才引入中间源集(skikoMain、appleMain)。

下面会详细介绍两个边界:由 Activity 持有的平台 UI 边界,以及 AGP-9 KMP 库的约束。

相关内容: android-skills:kmp-ktor(网络边界)、compose/references/multiplatform.md(Compose-MP 机制)、android-skills:kotlin-coroutines(作用域所有权)。对于 iOS↔Swift 桥接——Kotlin→Swift 命名、类型宽度(Int 为 32 位)、SKIE suspend→async / Flow→AsyncSequence、密封类完备性、SwiftUI 嵌入——编写 iOS 端 actual 时,请加载 references/ios-interop.md。

平台 UI 绑定由 Activity 持有,而非 Context 持有

Android 边界中最常见的错误是:将 applicationContext / LocalContext.current 传入实际上需要 Activity 的绑定,然后用 Intent.FLAG_ACTIVITY_NEW_TASK 来掩盖生命周期缺口。这个标志是个警示信号——它掩盖了这是一项前台 UI 操作的事实。应持有 Activity。

// commonMain — semantic interface; DOCUMENT what `suspend` means
interface ShareSheet {
    /** Launches the system share sheet. Returns when the sheet is PRESENTED — not when the user
     *  completes or cancels. (Otherwise callers write incorrect retry/confirmation logic.) */
    suspend fun shareText(text: String)
}

// androidMain — thin: build the intent and launch it. Activity-owned.
class AndroidShareSheet(private val activity: Activity) : ShareSheet {
    override suspend fun shareText(text: String) {
        activity.startActivity(Intent.createChooser(
            Intent(Intent.ACTION_SEND).setType("text/plain").putExtra(Intent.EXTRA_TEXT, text), null,
        ))
    }
}

不要在整个应用范围内注入 Activity(它由框架创建,并受生命周期约束)——应在 Android 应用模块的 Activity 作用域中构建绑定(Hilt 使用 @InstallIn(ActivityComponent::class),其中 Activity 是默认绑定;Koin 使用 scoped)。commonMain 只会看到接口;Activity 不会离开应用模块。如果生命周期更长的(应用作用域)对象需要它,应通过感知生命周期的提供方持有它(在 onResume 中设置,在 onPause 中清除),以免已销毁的 Activity 发生泄漏。

AGP 9 KMP 库的限制(结构性限制——决定共享代码中可以包含哪些内容)

AGP 9 将 KMP 模块 Android 端的 com.android.library 替换为 com.android.kotlin.multiplatform.library,并彻底拒绝 com.android.application + kotlin.multiplatform 的组合。新插件强制采用单变体架构:

  • 无法使用 BuildConfig——编译时常量应来自 BuildKonfig 或注入的 AppConfiguration 接口。设计 commonMain API 时,不要假设存在 BuildConfig.X。
  • 没有构建变体——特定变体的依赖项、资源和签名应放在应用模块中;debug/release 的区别应作为运行时配置值注入共享代码,而不是在 KMP 模块内部拆分构建变体。
  • 没有 NDK / JNI——将原生代码(C/C++)提取到单独的 com.android.library 模块中,并通过 KMP 模块使用的公共接口进行封装。
  • 必须显式启用 Compose-MP 资源——在 kotlin { android { … } } 内添加 androidResources { enable = true },否则 Android 上的 Res.string.* / Res.drawable.* 会在运行时崩溃(构建仍会成功——很容易忽略这一点)。
  • 必须迁移 Consumer ProGuard 规则——旧 android {} 块中的 consumerProguardFiles("rules.pro") 会被静默丢弃;请在新 DSL 中使用 consumerProguardFiles.add(file("rules.pro"))。
  • KMP 模块不能同时使用 com.android.application——Android 入口点(MainActivity、Application 类、启动器清单、applicationId / targetSdk / versionCode / versionName)需要移到依赖共享库的单独 androidApp 模块中。MainActivity、应用级 Hilt 配置和导航主机接线都要从共享的 androidMain 中移出。
  • kapt 与 AGP 9 内置 Kotlin 不兼容——将注解处理器迁移到 KSP(2.3.1+),或对于没有 KSP 对应版本的处理器,改用 com.android.legacy-kapt。
关注点AGP 9 之前(单体式)AGP 9 KMP 库
MainActivity、Application 类、启动器清单共享模块的 androidMain单独的 androidApp 模块
applicationId、versionCode、targetSdk共享模块的 android {}仅限 androidApp
编译时常量(环境、标志)BuildConfig 字段common 中的 BuildKonfig,或运行时 DI
NDK / JNI 原生代码androidMain(任意模块)单独的 com.android.library,通过公共接口封装

迁移现有项目时,请参阅 JetBrains 的 kotlin-tooling-agp9-migration 技能,了解完整流程。

评论

支持 Markdown