首页 > 解决方案 > 为什么作者需要用viewModelScope.launch包装一个非挂起函数?

问题描述

代码 A 来自项目架构示例,您可以在此处查看

filterItems是一个普通函数,当调用private fun filterTasksfilterItems,它被包裹着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
    }

    ...

}

标签: kotlinkotlin-coroutines

解决方案


这个函数是从主线程调用的(响应switchMap另一个 LiveData 上的 a ),它启动协程Dispatchers.Main(默认为viewModelScope),所以这实际上会将协程中的操作推迟到主线程中的所有其他当前任务之后线程队列完成。

有时这对于在一帧中给出快速的视觉指示很有用。

在这种情况下,协程前面的行会更改加载指示器的 LiveData。因此,他们希望加载指示器有机会在更新任务的列表视图之前隐藏在 UI 中可能是有原因的。也许在 UI 方面,这将导致更优雅的过渡。

或者另一种可能性:该协程中曾经有一个长时间运行的挂起函数调用,它被重构了,并且他们未能删除该协程。这不是我第一次在示例中遇到错误或代码异味。

即使这不是偶然的,但在这种情况下,确实需要在代码中添加注释来解释它,因为它是不明显的。


推荐阅读