Jetpack Compose中viewModel的使用、viewModel多实例

前言

使用 viewModel 我们可以方便管理模型数据的生命周期。

简单使用

1
import androidx.lifecycle.viewmodel.compose.viewModel

类继承ViewModel

1
2
3
class MainSubjectPageVm : ViewModel() {

}

组件中生成实例

1
val mViewModel: MainSubjectPageVm = viewModel()

但是如果我们有多个组件,组件有自己的ViewModel,这时候数据就乱套了。

是因为

默认情况下ViewModel 是与 Activity 或 Fragment 的生命周期 绑定的。

也就是说

即使同一个 Activity/Fragment 中有多个相同的子组件(如多个自定义 View 或 Compose 组件),只要它们使用 viewModel() 函数获取实例,得到的会是同一个实例

这是因为 ViewModel 的作用域是整个 Activity/Fragment,而非单个子组件。

多实例

如果需要多个实例,可以通过指定不同的 ViewModelStoreOwner 来实现:

管理类

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
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner

private class ComponentViewModelStoreOwner : ViewModelStoreOwner {
private val store = ViewModelStore()

override val viewModelStore: ViewModelStore
get() = store
}

// 记住自定义的ViewModelStoreOwner,并在组件销毁时清理
@Composable
fun rememberComponentViewModelStoreOwner(): ViewModelStoreOwner {
val owner = remember { ComponentViewModelStoreOwner() }

// 当组件离开组合树时,清理ViewModelStore
DisposableEffect(Unit) {
onDispose {
owner.viewModelStore.clear()
}
}
return owner
}

组件中使用

1
2
3
4
// 为每个组件创建独立的ViewModelStoreOwner
val independentStoreOwner = rememberComponentViewModelStoreOwner()
// 使用独立作用域获取ViewModel
val mViewModel: MainSubjectPageVm = viewModel(viewModelStoreOwner = independentStoreOwner)