You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Compose中两种ViewModel初始化方式为何状态保留不同

关于Compose中ViewModel状态保留的疑问与解答

我的可组合函数

@Composable
fun CounterScreen(viewModel: MyViewModel = viewModel()) {
    val uiState by viewModel.uiState.collectAsState()

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "Counter: ${uiState.count}")
        Spacer(modifier = Modifier.height(16.dp))
        FloatingActionButton(
            onClick = {
                viewModel.increment()
            },
        ) {
            Icon(imageVector = Icons.Default.Add, contentDescription = "Increment")
        }
    }
}

疑问

当我使用fun CounterScreen(viewModel: MyViewModel = viewModel())时,重组过程中状态能够被保留;但使用fun CounterScreen(viewModel: MyViewModel = MyViewModel())时,状态却无法保留。然而两种方式看起来都会创建MyViewModel的新实例,请问这是为什么?


解答

这两种方式的核心区别在于ViewModel实例的管理机制:

  • viewModel()函数并非每次调用都创建新实例:
    viewModel()是Jetpack Compose提供的专门用于获取ViewModel的工具函数,它会绑定到当前的ViewModelStoreOwner(比如宿主Activity、Fragment或者导航栈条目)。第一次调用时会创建ViewModel实例并存储起来,后续重组或配置变化(如屏幕旋转)时,会直接复用已存储的实例,不会创建新对象,因此状态得以保留。

  • 直接调用MyViewModel()会每次重组都生成新实例:
    Compose的重组会根据状态变化多次执行可组合函数的代码逻辑,每次执行到MyViewModel()这一行时,都会创建一个全新的ViewModel实例。旧实例会被丢弃,之前保存的状态自然也就丢失了。

简单来说,viewModel()帮你完成了实例的缓存与生命周期绑定,而直接new的方式完全绕过了这套管理机制,自然无法保留状态。

内容的提问来源于stack exchange,提问作者Turvy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 12:55:05