You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将ViewModelScope中初始化的var类型todoList改为val?

解决方案:将ViewModel中的var todoList改为val

核心思路

把var todoList改成val的关键是复用同一个MutableStateList实例,更新列表内容而非替换整个对象,避免重新赋值变量。

修改后的代码(保留todoList的场景)

class MainViewModel(private val todoDao: TodoDao) : ViewModel() {
    // 改为val,初始化空的可变状态列表
    private val todoList = mutableStateListOf<TodoItem>()
    private val _todoListFlow = MutableStateFlow<List<TodoItem>>(todoList)

    val todoListFlow: StateFlow<List<TodoItem>> get() = _todoListFlow
    private var postExecute: (() -> Unit)? = null

    init {
        loadTodoList()
    }

    private fun loadTodoList() {
        viewModelScope.launch {
            todoDao.getAll().collect { newItems ->
                // 清空原有内容,添加新数据,复用同一个列表实例
                todoList.clear()
                todoList.addAll(newItems)
                // 手动触发StateFlow发射,因为列表引用未变,仅内容更新
                _todoListFlow.value = todoList
                postExecute?.invoke()
            }
        }
    }
}

简化优化方案(无需单独维护todoList)

如果你的场景不需要本地修改todoList,仅需展示Dao返回的数据,可以直接将Dao的Flow转换为StateFlow,全程无需可变变量:

class MainViewModel(private val todoDao: TodoDao) : ViewModel() {
    // 直接通过stateIn将Flow转为StateFlow,全程val
    val todoListFlow: StateFlow<List<TodoItem>> = todoDao.getAll()
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000), // 订阅者取消后延迟5秒停止收集
            initialValue = emptyList()
        )
    private var postExecute: (() -> Unit)? = null

    init {
        // 若需在数据首次加载后执行postExecute,可监听todoListFlow
        viewModelScope.launch {
            todoListFlow.first()
            postExecute?.invoke()
        }
    }
}

关键说明

  1. 对于保留todoList的场景:MutableStateList本身是可观察的状态容器,清空并添加新数据不会改变列表引用,符合val的不可变特性;由于StateFlow仅在值引用变化时发射事件,因此需要手动赋值_todoListFlow.value = todoList来通知订阅者。
  2. 简化方案更符合Jetpack架构最佳实践,减少了冗余的状态维护,同时完全满足val的需求。

内容的提问来源于stack exchange,提问作者Elye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 23:16:14