本文译自Four useful tips for Compose Kotlin Multiplatform (KMP)
译注: 这篇文章虽然比较短,但提到的问题还是比较具体和典型的,针对CMP项目的一些配置还是很有借鉴意义的。
简介
正如我在上一篇文章《将多模块应用程序完全迁移到 Compose Kotlin Multiplatform (KMP)》 中所说,上个月我一直在将现有的多模块应用程序迁移到 Compose Multiplatform,除此之外,我还从头开始创建一个新的 Compose Multiplatform 多模块项目。在这两个项目中,我都遇到了相同的“问题”或者说“阻碍”,因此,如果您正在迁移或从头开始启动 CMP 项目,那么本文就是为你量身定做的。
提示 1:预览
KMP 不支持 commonMain 目录Compose组件的预览,因此我想到了在 androidMain 目录中创建它们,并且它们的预览运行得很好。
译注: 此文原文发布于2024年12月初,彼时非Android侧的源码确实无法Preview,后来JetBrains解决了这个问题,通过一个支持桌面Compose的插件 。
例如:
1
2
commonMain/com/example/feature/component/FeatureScreen.kt
androidMain/com/example/feature/component/FeatureScreenPreview.kt
提示 2:BackHandler
KMP 不支持 BackHandler 操作,因此我创建了一个用于屏幕的expect函数,并在 androidMain 中的actual函数上添加了 BackHandler 操作,并将 iosMain 留空(因为我在 iOS 中没有找到类似的操作)。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
// commonMain/ com.example.feature.component.FeatureScreen.kt
@Composable
expect fun FeatureScreen (
viewModel : FeatureScreenViewModel ,
)
@Composable
internal fun Content (
viewModel : FeatureScreenViewModel ,
) {
...
}
1
2
3
4
5
6
7
8
9
10
11
12
// androidMain/ com.example.feature.component.FeatureScreenActual.kt (needs a name different from common)
@Composable
actual fun FeatureScreen (
viewModel : WorkScreenViewModel ,
) {
BackHandler { viewModel . onIntent ( WorkIntent . Back ) }
Content (
viewModel = viewModel ,
)
}
// extra: I have joined the preview in this same class to have it better organized.
1
2
3
4
5
6
7
8
9
// iosMain/ com.example.feature.component.FeatureScreenActual.kt (needs a name different from common)
@Composable
actual fun FeatureScreen (
viewModel : WorkScreenViewModel ,
) {
Content (
viewModel = viewModel ,
)
}
提示 3:测试模拟
我喜欢使用 mockk 库进行模拟测试,在撰写本文时,KMP 尚不支持该库,因此我决定在 androidUnitTest 目录中创建 UnitTest,并将库依赖项添加到 androidUnitTest.dependencies {} 块中。
对于此类测试,我使用了支持 KMP 的 kotlin-test jetbrains 库。
例如:
1
2
mockk = { group = "io.mockk" , name = "mockk" , version . ref = "mockk-version" }
kotlin - test = { group = "org.jetbrains.kotlin" , name = "kotlin-test" , version . ref = "kotlin-version" }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// feature build.gradle.kts
kotlin {
...
sourceSets {
androidUnitTest . dependencies {
implementation ( libs . mockk )
}
commonTest . dependencies {
implementation ( libs . kotlin . test )
}
}
}
1
androidUnitTest/com/example/feature/usecase/UseCaseTest.kt
提示 4:UI 测试
官方的 Compose 多平台 UI 测试指南 指出,必须使用commonTest 目录进行 UI 测试,但我更喜欢使用androidInstrumentedTest目录,因为使用这种方法,我可以将单元测试与 UI 测试分开,并且我可以直接从同一个测试类执行它们,并从目录运行所有 UI 测试。
例如:
1
2
3
4
mockk - android = { group = "io.mockk" , name = "mockk-android" , version . ref = "mockk-version" }
ui - test - junit4 - android = { group = "androidx.compose.ui" , name = "ui-test-junit4-android" , version . ref = "uiTestJunit4AndroidVersion" }
ui - test - manifest = { group = "androidx.compose.ui" , name = "ui-test-manifest" , version . ref = "uiTestManifestVersion" }
kotlin - test = { group = "org.jetbrains.kotlin" , name = "kotlin-test" , version . ref = "kotlin-version" }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// feature build.gradle.kts
plugins {
...
alias ( libs . plugins . compose . multiplatform )
alias ( libs . plugins . compose )
}
kotlin {
...
sourceSets {
androidInstrumentedTest . dependencies {
implementation ( libs . mockk . android )
implementation ( libs . ui . test . junit4 . android )
}
commonTest . dependencies {
implementation ( libs . kotlin . test )
@OptIn ( ExperimentalComposeLibrary :: class )
implementation ( compose . uiTest )
}
}
}
...
dependencies {
debugImplementation ( libs . ui . test . manifest )
}
1
androidInstrumentedTest/com/example/feature/component/ScreenAndroidTest.kt
结论
在本文中,我们看到了一些 Compose Multiplatform 技巧,希望您觉得它们有用。感谢您阅读本文,欢迎提供任何反馈。