3. Compose Multiplatform项目初始化
原理概述
Compose Multiplatform 项目的初始化核心在于 共享模块(shared module) 的 Gradle 配置。该模块必须声明 Compose 插件、多平台目标(Android / iOS)、以及所需的外部依赖(Ktor、ViewModel 等)。依赖管理推荐使用 版本目录(Version Catalog) 统一管理版本号,避免硬编码。
本章将详细拆解从根项目到 shared 模块的完整配置流程,涵盖 Ktor HTTP 客户端与 ViewModel 生命周期的依赖引入方式。
Gradle 配置:根项目与 shared 模块
根项目 build.gradle.kts
根项目负责声明插件版本与 版本目录 的入口。推荐使用 libs.versions.toml 管理所有依赖版本。
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.kotlinMultiplatform) apply false
alias(libs.plugins.composeMultiplatform) apply false
alias(libs.plugins.composeCompiler) apply false
}
// settings.gradle.kts 中添加版本目录引用
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
shared 模块 build.gradle.kts
这是整个项目的核心。必须应用 kotlin("multiplatform")、id("org.jetbrains.compose") 以及 compose.compiler 插件。同时声明 Android、iOS 目标。
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
}
kotlin {
androidTarget {
compilations.all {
kotlinOptions { jvmTarget = "17" }
}
}
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "shared"
isStatic = true
}
}
sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(libs.ktor.client.core)
implementation(libs.viewmodel.compose)
}
androidMain.dependencies {
implementation(libs.ktor.client.okhttp)
}
iosMain.dependencies {
implementation(libs.ktor.client.darwin)
}
}
}
android {
namespace = "com.example.shared"
compileSdk = 34
defaultConfig { minSdk = 24 }
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
依赖管理:版本目录(Version Catalog)
在项目的 gradle/libs.versions.toml 中集中定义版本号。典型内容如下:
[versions]
kotlin = "2.0.21"
compose-multiplatform = "1.7.1"
ktor = "3.0.2"
viewmodel = "0.12.0"
coroutines = "1.9.0"
[libraries]
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
viewmodel-compose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "viewmodel" }
[plugins]
androidApplication = { id = "com.android.application", version = "8.7.3" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
androidLibrary = { id = "com.android.library", version = "8.7.3" }
build.gradle.kts 中的硬编码版本,仅通过 libs.versions.toml 管理。Ktor 客户端配置
在 commonMain 中声明 Ktor 核心依赖后,需要为平台提供实际的 Engine 实现。典型的 expect/actual 模式:
// commonMain 中的 expect 声明
expect fun createPlatformHttpClient(): HttpClient
// androidMain 中的 actual
actual fun createPlatformHttpClient(): HttpClient {
return HttpClient(OkHttp) {
install(ContentNegotiation) { json() }
}
}
// iosMain 中的 actual
actual fun createPlatformHttpClient(): HttpClient {
return HttpClient(Darwin) {
install(ContentNegotiation) { json() }
}
}
此外,也可在 commonMain 中直接使用 HttpClient() 配合 ktor-client-core,但 不推荐——缺失平台 Engine 会在运行时崩溃。务必始终通过 expect/actual 提供平台版本。
ViewModel 配置
Compose Multiplatform 的 ViewModel 由 lifecycle-viewmodel-compose 库提供。该库已在 commonMain dependencies 中引入。使用时需注意:
- ViewModel 在
commonMain中定义为普通类,继承ViewModel()(来自androidx.lifecycle.ViewModel)。 - 通过
viewModel()函数在 Composable 中获取实例——该函数由lifecycle-viewmodel-compose提供。 - 无需在 Android 侧额外添加依赖(该库已为 Android 提供实际实现)。
// commonMain 中的 ViewModel 示例
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
class CounterViewModel : ViewModel() {
private val _count = MutableStateFlow(0)
val count = _count.asStateFlow()
fun increment() {
_count.value += 1
}
}
// Compose 中使用
@Composable
fun CounterScreen() {
val vm: CounterViewModel = viewModel()
val count by vm.count.collectAsState()
// UI ...
}
调试技巧
- Gradle 构建分析: 使用
--info或--scan参数查看依赖解析详情。若出现版本冲突,优先检查libs.versions.toml中的 Ktor 和 ViewModel 版本是否与 Compose 版本兼容。 - iOS 端测试: 确保
iosMain的 Ktor Engine 依赖正确(ktor-client-darwin)。运行 iOS 模拟器时如果报错Module not found: darwin,请清理 Gradle 缓存并重新同步。 - Ktor 日志: 添加
Logging插件可以输出 HTTP 请求/响应细节:install(Logging) { level = LogLevel.BODY }。
常见错误
| 错误现象 | 根本原因 | 解决方案 |
|---|---|---|
Unresolved reference: ktor.client.core |
版本目录中未声明 Ktor 库或版本号错误 | 检查 libs.versions.toml 的 [libraries] 部分,确保 ktor-client-core 条目正确 |
Symbol 'ViewModel' is unresolved |
lifecycle-viewmodel-compose 依赖未添加至 commonMain |
在 commonMain.dependencies 中添加 implementation(libs.viewmodel.compose) |
iOS 编译失败:Undefined symbols for architecture arm64 |
iOS 端 Ktor Engine 缺失 | 在 iosMain.dependencies 中添加 ktor-client-darwin |
Android 端编译时提示 Duplicate class |
Ktor 的多个 Engine 被同时引入(如 okhttp + android) | 只保留 androidMain 中一个 Engine 依赖,移除其他平台 Engine |
性能与稳定性优化
- Ktor 插件按需安装: 仅在需要时添加
ContentNegotiation、Logging等插件,避免不必要的序列化开销。 - ViewModel 作用域: 使用
viewModelScope管理协程生命周期,避免在 Composable 中直接启动协程导致内存泄漏。 - 依赖版本锁定: 将
libs.versions.toml中的所有版本统一为稳定版,避免使用+通配符。例如:ktor = "3.0.2"而非3.0.+。 - Android 混淆规则: 若启用 R8 / ProGuard,需在
consumer-rules.pro中添加 Ktor 与 ViewModel 的保留规则:
-keepclassmembers class * extends androidx.lifecycle.ViewModel {
<init>(...);
}
-keep class io.ktor.** { *; }