Android 收集 Flow 时在主线程上做太多工作
Android doing too much work on its main thread when collecting Flow
我有一个本地数据库功能,returns Flow 格式的用户列表。 Flow<List<User>>
。主屏幕仅显示最新的用户列表。启动应用程序并预填充数据库时,流程首先接收空列表,然后在预填充完成时接收更新的列表。
这会导致 Android to do too much work on its main thread
并跳过渲染帧。
viewModelScope.launch {
dao.getUsers().collect {
userList.value = it
}
}
如果我们像 above-mentioned 那样只处理最新数据,性能可以得到改善,我们不需要每个发出的用户列表,我们只需要最新的用户列表。这样我们就不会浪费资源处理每个发出的列表。
Kotlin Flow 有另一个运算符 collectLatest{}
,它与 collect{}
有点不同。
collect{}
- 这将收集每个发出的数据。
collectLatest{}
- 这将在发出新值时取消收集器。
viewModelScope.launch {
dao.getUsers().collectLatest {
userList.value = it
}
}
如果我们只需要收集 non-empty 列表,我们可以简单地过滤掉空的发射列表。
viewModelScope.launch {
dao.getUsers()
.filter { it.isNotEmpty() }
.collectLatest {
userList.value = it
}
}
我有一个本地数据库功能,returns Flow 格式的用户列表。 Flow<List<User>>
。主屏幕仅显示最新的用户列表。启动应用程序并预填充数据库时,流程首先接收空列表,然后在预填充完成时接收更新的列表。
这会导致 Android to do too much work on its main thread
并跳过渲染帧。
viewModelScope.launch {
dao.getUsers().collect {
userList.value = it
}
}
如果我们像 above-mentioned 那样只处理最新数据,性能可以得到改善,我们不需要每个发出的用户列表,我们只需要最新的用户列表。这样我们就不会浪费资源处理每个发出的列表。
Kotlin Flow 有另一个运算符 collectLatest{}
,它与 collect{}
有点不同。
collect{}
- 这将收集每个发出的数据。collectLatest{}
- 这将在发出新值时取消收集器。
viewModelScope.launch {
dao.getUsers().collectLatest {
userList.value = it
}
}
如果我们只需要收集 non-empty 列表,我们可以简单地过滤掉空的发射列表。
viewModelScope.launch {
dao.getUsers()
.filter { it.isNotEmpty() }
.collectLatest {
userList.value = it
}
}