kotlin - 为什么作者需要用viewModelScope.launch包装一个非挂起函数?
问题描述
代码 A 来自项目架构示例,您可以在此处查看。
filterItems
是一个普通函数,当调用private fun filterTasks
时filterItems
,它被包裹着viewModelScope.launch
。
在我看来,通常挂起函数可能会被触发viewModelScope.launch
,系统会等到得到结果。
为什么作者需要用 包装一个非挂起函数viewModelScope.launch
?
代码 A
class TasksViewModel(
private val tasksRepository: TasksRepository,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
private fun filterTasks(tasksResult: Result<List<Task>>): LiveData<List<Task>> {
// TODO: This is a good case for liveData builder. Replace when stable.
val result = MutableLiveData<List<Task>>()
if (tasksResult is Success) {
isDataLoadingError.value = false
viewModelScope.launch { //Why wrapped with viewModelScope.launch
result.value = filterItems(tasksResult.data, getSavedFilterType())
}
} else {
result.value = emptyList()
showSnackbarMessage(R.string.loading_tasks_error)
isDataLoadingError.value = true
}
return result
}
private fun filterItems(tasks: List<Task>, filteringType: TasksFilterType): List<Task> {
val tasksToShow = ArrayList<Task>()
// We filter the tasks based on the requestType
for (task in tasks) {
when (filteringType) {
ALL_TASKS -> tasksToShow.add(task)
ACTIVE_TASKS -> if (task.isActive) {
tasksToShow.add(task)
}
COMPLETED_TASKS -> if (task.isCompleted) {
tasksToShow.add(task)
}
}
}
return tasksToShow
}
...
}
解决方案
这个函数是从主线程调用的(响应switchMap
另一个 LiveData 上的 a ),它启动协程Dispatchers.Main
(默认为viewModelScope
),所以这实际上会将协程中的操作推迟到主线程中的所有其他当前任务之后线程队列完成。
有时这对于在一帧中给出快速的视觉指示很有用。
在这种情况下,协程前面的行会更改加载指示器的 LiveData。因此,他们希望加载指示器有机会在更新任务的列表视图之前隐藏在 UI 中可能是有原因的。也许在 UI 方面,这将导致更优雅的过渡。
或者另一种可能性:该协程中曾经有一个长时间运行的挂起函数调用,它被重构了,并且他们未能删除该协程。这不是我第一次在示例中遇到错误或代码异味。
即使这不是偶然的,但在这种情况下,确实需要在代码中添加注释来解释它,因为它是不明显的。
推荐阅读
- sql-server - 如何将 context_info 返回值转换为 xml
- php - php中的sql命令可以用“。”从其他变量中设置吗?连接器?
- python - Python - 字符串到 JSON。错误:AttributeError:“str”对象没有属性“get”
- python - 我正在尝试创建一个程序,将 2 个(用户)输入转换为列表,然后在列表中打印重复项
- mysql - 获取具有最大值的单元格的整行/行
- python - 减少 python 上的 if 语句数量
- java - org.postgresql.util.PSQLException:错误:关系“userdetailsentity”不存在
- react-native - 我尝试安装弹出对话框以响应本机
- node.js - ENV 变量未从 Docker 传递到节点 JS 代码
- javascript - 如何在javascript函数中将日期作为参数传递