Jetpack Compose中viewModel监听数据变化

前言

有这么一个场景,我们的组件是单词的详情,组件传入的是wordId,获取单词的详细信息。

如果这样定义

1
val wordId = mutableStateOf("")

我们可以在Compose和ViewModel中获取和设置这个值。

但是我们没法监听这个值的变化。

为什么要监听变化呢?

我们要根据这个变化调用接口获取详情,我们可以在Compose的重组事件中调用获取数据,但是这样就会每次组件重组都触发了调用。

我们想要的是就算页面销毁了,再次渲染依旧不用重新调用接口。

这就可以使用MutableStateFlow来实现:

MutableStateFlow

对于组件传入变量引发的数据处理可以使用MutableStateFlow。

ViewModel

ViewModel中使用MutableStateFlow定义变量,并监听变化,这样只有变化才会调用接口。

因为ViewModel的生命周期和Activity绑定的,所以就算页面重组,数据依旧保留。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private val _wordId = MutableStateFlow("")

fun setWordId(id: String) {
_wordId.value = id
}

init {
viewModelScope.launch {
_wordId.collect {
if (_wordId.value.isNotEmpty()) {
actionInit()
}
}
}
}

Compose

页面中只用设置变化的值就行

1
vm.setWordId(wordId)

不用再这样调用

1
2
3
LaunchedEffect(wordId) {
vm.actionInit()
}

页面中要使用

如果页面重组要使用这个变量

ViewModel中这样暴漏出来

1
2
private val _wordId = MutableStateFlow("")
val wordId: StateFlow<String> = _wordId.asStateFlow()

Compose中这样取

1
val wordId by vm.wordId.collectAsStateWithLifecycle()

MutableState

其他的数据获取为了书写方便,可以这样写

1
val list = mutableStateListOf<WordMean>()

当然推荐写法还是都用上面的方式。