Search code examples
androidkotlinkotlin-coroutinesandroid-viewmodel

How can I initialize a val that need to be initialize through viewModelScope?


I have the below code

class MainViewModel(private val todoDao: TodoDao) : ViewModel() {
    private var todoList = mutableStateListOf<TodoItem>()
    private val _todoListFlow = MutableStateFlow(todoList)

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

    init {
        loadTodoList()
    }

    private fun loadTodoList() {
        viewModelScope.launch {
            todoDao.getAll().collect {
                todoList = it.toMutableStateList()
                _todoListFlow.value = todoList
                postExecute?.invoke()
            }
        }
    }
}

You notice the var todoList is var.

Since it get initialize only once, I hope to make it val. How is that possible, given it is initialized in the viewModelScope?


Solution

  • It is unclear why you are using a mixture of MutableStateFlow and SnapshotStateList to end up with MutableStateFlow<SnapshotStateList<TodoItem>> when there is really no need for the _todoListFlow, but to answer your question simply initialise the SnapshotStateList then upon collection modify the data structure contents :

    class MainViewModel(private val todoDao: TodoDao) : ViewModel() {
        private val todoList = mutableStateListOf<TodoItem>()
        private val _todoListFlow = MutableStateFlow(todoList)
    
        val todoListFlow: StateFlow<List<TodoItem>> get() = _todoListFlow
        private var postExecute: (() -> Unit)? = null
    
        init {
            loadTodoList()
        }
    
        private fun loadTodoList() {
            viewModelScope.launch {
                todoDao.getAll().collect {
                    todoList.clear() // optional if getAll has multiple emissions?
                    todoList.addAll(it)
                    _todoListFlow.value = todoList
                    postExecute?.invoke()
                }
            }
        }
    }