如何在 KotlinMultiplatform 项目中的target之间共享代码

在一些场景下,使用 KMP 会存在一些碎片化问题

例如同样使用 kotlin-reflect,只在 jvm、Android 下可以获得完整的反射体验。

在 ios 平台、common 平台都无法使用如下代码:

inline fun <reified T> checkCompanionObject(): Tuple3<Any, KFunction<*>, KFunction<*>> {
    val companionObj = T::class.companionObjectInstance
    val companionKClass = companionObj::class
    val defaultMethod = companionKClass.functions.firstOrNull { it.name == "default" }
    val optionOfMethod = companionKClass.functions.firstOrNull { it.name == "optionOf" }
    return tuple(companionObj, defaultMethod, optionOfMethod)
}

T::class.companionObjectInstance 这个获取伴生对象的扩展属性就无法支持 ios、js 等平台。

那如果我们只想给 jvm、android 提供这个函数,将这份代码写到两个源集中无疑不方便后续的管理、修改。

我们可以在src目录下新建一个源集目录:commonJvmAndroid,将代码按照正确的路径放置于该源集之下

sourceSet

然后回到 build.gradle.kts 中进行如下修改

val commonJvmAndroid by creating {
    dependsOn(commonMain.get())
} // 创建在jvm、Android中共享的源集
​
// 在需要共享代码的源集中依赖
androidMain.get().dependsOn(commonJvmAndroid)
​
val desktopMain by getting {
    dependsOn(commonJvmAndroid)
}

类似的,有的 kmm 库(例如mmkv-kotlin)只支持 ios、android,对 jvm 桌面不支持。

我们可以在 commonMain 中 通过 expect 创建相关期望函数,创建一个 commonIosAndroid 源集依赖该库,通过使用 kmm 库提供的能力进行 actual,然后自行为 jvm 桌面平台单独实现,这样通过这个库可以覆盖的多个 target 只需要写一个 actual 即可。

写在最后

ComposeHooks  项目现已支持 CMP,可以使用快照版本进行尝鲜,工件 id 由hooks 变更为 hooks2

1
2
3
maven("https://s01.oss.sonatype.org/content/repositories/snapshots")

implementation("xyz.junerver.compose:hooks2:2.1.0-alpha0-SNAPSHOT")