上回簡單說了如何使用,這次就要開始實操
在真正的設計前,需要先考量需要的功能與資料,但大部分還是邊寫邊加
在這個專案中,我們需要一個todoList,被選取的todo和是否是update的輸入
其中需要的延伸功能有Group的list等
data class TodoItem(
var title: String = "",
var content: String = "",
var group: String = "",
var done: Boolean = false
)
class GlobalVM : ViewModel() {
private val _todoList = MutableStateFlow<List<TodoItem>>(emptyList())
val todoList: StateFlow<List<TodoItem>> = _todoList
private val _isUpdate = MutableStateFlow<Boolean>(false)
private val _currentTodo = MutableStateFlow<TodoItem>(TodoItem())
val currentTodo: StateFlow<TodoItem> = _currentTodo
// TodoList
fun submitTodo(todoItem: TodoItem) {}
fun checkedTodo(todoItem: TodoItem, checked: Boolean) {}
// Check update
fun resetUpdate() {}
// CurrentTodo
fun focusTodo(todoItem: TodoItem) {}
// Current Group
fun focusGroup(groupName: String) {}
}
這邊沒有將_isUpdate
設成public,因為我認為他是屬於邏輯層處理的一個flag,其中
resetUpdate()
主要是保護機制,避免畫面切換後還殘留「更新狀態」focusTodo()
是進入編輯模式,UI 層可以依照 _isUpdate
的值來決定要顯示「新增」還是「更新」的按鈕由於這個應用十分的簡單,所以並不用兩個viewmodel,也沒有很多的邏輯
既然大概知道需要甚麼資料與功能,就可以著手設計邏輯部分
這邊沒有設計刪除的功能是因為這邊還停留在展示階段,具體的CRUD會由資料庫完成
首先就是提交todo,我考慮了這是更新還是單純的新增,以及按下checkedbox的情況
fun submitTodo(todoItem: TodoItem) {
if (_isUpdate.value){
_todoList.update { list ->
list.map { if (it == _currentTodo.value) todoItem else it }
}
_isUpdate.update { false }
}
else
_todoList.update { it + todoItem }
}
fun checkedTodo(todoItem: TodoItem, checked: Boolean) {
_todoList.update { list ->
list.map { if (it == todoItem) todoItem.copy(done = checked) else it }
}
}
我想在todo的地方可以按更新,這樣他就可以進入更新狀態,但如果畫面切掉就不會進這個狀態
fun resetUpdate() {
_isUpdate.update { false }
_currentTodo.update { TodoItem() }
}
在todo被按下更改的時候就會觸發,並把使用者跳轉到輸入畫面
fun focusTodo(todoItem: TodoItem) {
_isUpdate.update { true }
_currentTodo.update { todoItem }
}
// Current Group
fun focusGroup(groupName: String) {
_currentGroup.update { groupName }
}
這樣就設計完了非常基礎的viewmodel
下一步就是把這些狀態接到 Composable 上,讓我們能做到: