上一篇講了如何建立一個Room database
這一篇要將原本的資料變成SQL的資料流,並替換部分邏輯
先把原本viewmodel中使用到todoList的部份去掉,並添加查詢函數(group name, todo list)
// SQL query
fun getGroupTodo(group: String): Flow<List<TodoItem>> {
return todoDao.getGroupItems(group)
}
fun getGroupInfo(): Flow<List<GroupInfo>> {
return todoDao.getGroupsInfo()
}
// TodoList
fun submitTodo(todoItem: TodoItem): Boolean {
// Check valid
if (todoItem.group == "" || todoItem.title == "") return false
if (_isUpdate.value){ // update
todoDao.update(todoItem)
_isUpdate.update { false }
}
else // insert
todoDao.insert(todoItem)
return true
}
fun checkedTodo(todoItem: TodoItem, checked: Boolean) {
todoDao.update(todoItem.copy(done = checked))
}
之後就可以把todoList刪除了
檢查各個有出問題的UI函數
val group by globalVM.currentGroup.collectAsState()
val todoList by globalVM.getGroupTodo(group).collectAsState(emptyList())
並將items裡的filter去除
@Composable
fun TodoGroups(
globalVM: GlobalVM,
navController: NavController) {
val groupList by globalVM.getGroupInfo().collectAsState(emptyList())
LazyColumn{
items(items = groupList) { groupInfo->
GroupItem(groupInfo) {
globalVM.focusGroup(groupInfo.group)
navController.navigate(Screens.Main.Todos.route){
launchSingleTop = true
}
}
}
}
}
GroupItem這邊就不展示了
val groupNameList by globalVM.getGroupInfo().collectAsState(emptyList())
// DropDownMenu
DropDownSelector(
groupNameList.map { it.group },
group,
)
這樣資料取得的地方就改得差不多了
因為我們自定義了ViewModel產生的方式,所以也要特別進行宣告
@Composable
fun App(modifier: Modifier = Modifier) {
val navController = rememberNavController()
// DB construct(reference)
val context = LocalContext.current
val todoDB = Room.databaseBuilder(
context,
AppDatabase::class.java,
"todoDB",
).build()
val todoDao = todoDB.todoDao()
val globalVM: GlobalVM = viewModel(
factory = GlobalViewModelFactory(todoDao)
)
這段看不懂也沒關係
現在啟動程式會發現一個todo都沒有,因為是資料庫剛建立,但當你想要add一下之後就會跳出
其實是因為資料庫存取有可能會阻斷主程式的運行,導致UI卡住,為了避免這種問題,所以就會跳出
這時候就要使用Coroutine呼叫
在所有使用到insert或update的地方套上
// at checked todo
viewModelScope.launch(Dispatchers.IO) {
todoDao.update(todoItem.copy(done = checked))
}
現在就可以正常運行了