如何在KMM Compose UI中实现MVVM架构?依赖同步报错求助
KMM Compose 中实现 MVVM 的可行方案及依赖报错解决
依赖报错原因
你添加的androidx.lifecycle.viewmodel.ktx、androidx.activity.ktx等依赖都是Android平台专属的,不能直接放在commonMain的依赖配置中——iOS没有对应的实现,所以Gradle同步时会在iOS目标平台(如iosArm64)找不到依赖文件,触发ArtifactResolveException错误。
跨平台 MVVM 实现方案
核心思路是:将ViewModel的业务逻辑、状态管理放在commonMain中共享,平台相关的生命周期适配分Android/iOS各自处理。
1. 定义跨平台的ViewModel基类(commonMain)
实现一个轻量的、不依赖AndroidX的基类,处理协程生命周期:
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel open class SharedViewModel { // 跨平台协程作用域,ViewModel销毁时自动取消 protected val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) // 销毁回调,用于清理资源 open fun onCleared() { viewModelScope.cancel() } }
2. 定义共享的UI状态与事件(commonMain)
用不可变数据类管理UI状态,密封类统一处理UI事件:
// UI状态:所有需要展示的数据都封装在这里 data class CounterState(val count: Int = 0) // UI事件:定义用户交互的所有类型 sealed class CounterEvent { object Increment : CounterEvent() object Decrement : CounterEvent() }
3. 实现业务ViewModel(commonMain)
用StateFlow管理状态,确保状态变化能被UI层感知:
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow class CounterViewModel : SharedViewModel() { // 内部可变状态,对外暴露不可变的StateFlow private val _state = MutableStateFlow(CounterState()) val state = _state.asStateFlow() // 处理UI事件,更新状态 fun handleEvent(event: CounterEvent) { when (event) { CounterEvent.Increment -> { _state.value = _state.value.copy(count = _state.value.count + 1) } CounterEvent.Decrement -> { _state.value = _state.value.copy(count = _state.value.count - 1) } } } override fun onCleared() { super.onCleared() _state.resetReplayCache() // 可选:清理状态缓存 } }
4. Android端整合Compose与生命周期
将共享ViewModel包装成AndroidX ViewModel,借助其自动生命周期管理:
- 首先在
androidMain的依赖中添加AndroidX相关库(不要放在commonMain):
androidMain.dependencies { implementation(libs.androidx.lifecycle.viewmodel.ktx) implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(libs.androidx.activity.compose) }
- 在Compose中使用:
// 包装成AndroidX ViewModel class AndroidCounterViewModel : androidx.lifecycle.ViewModel(), CounterViewModel by CounterViewModel() @Composable fun CounterScreen() { val viewModel = viewModel<AndroidCounterViewModel>() // 自动感知生命周期的状态收集 val state by viewModel.state.collectAsStateWithLifecycle() Column(modifier = Modifier.padding(16.dp)) { Text(text = "Count: ${state.count}") Button(onClick = { viewModel.handleEvent(CounterEvent.Increment) }) { Text("Increment") } Button(onClick = { viewModel.handleEvent(CounterEvent.Decrement) }) { Text("Decrement") } } }
5. iOS端适配生命周期
iOS没有AndroidX ViewModel的自动生命周期管理,需要手动调用销毁方法:
import UIKit import shared // 替换为你的KMM共享模块名称 class CounterViewController: UIViewController { private let viewModel = CounterViewModel() private var stateObserver: NSObjectProtocol? override func viewDidLoad() { super.viewDidLoad() // 监听StateFlow状态变化,更新UI stateObserver = viewModel.state.subscribe { [weak self] state in guard let self = self, let state = state else { return } self.countLabel.text = "Count: \(state.count)" } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 销毁ViewModel,取消协程 viewModel.onCleared() if let observer = stateObserver { NotificationCenter.default.removeObserver(observer) } } // 按钮点击事件 @IBAction func incrementTapped(_ sender: UIButton) { viewModel.handleEvent(event: CounterEventIncrement()) } @IBAction func decrementTapped(_ sender: UIButton) { viewModel.handleEvent(event: CounterEventDecrement()) } }
内容的提问来源于stack exchange,提问作者Gipfeli
相关产品推荐
相关产品推荐

