昨天使用 *toMutableStateList*()
讓 list 新增和移除可以讓畫面更新。
今天想要嘗試更改 list
的參數內容,讓內容也可以讓畫面更新。
title
原本的 type
是 String
,改成MutableState<>
就可以有狀態。
/**
* @param title 訓練名稱
* **/
data class TrainingItem(
//...
val title: MutableState<String> = mutableStateOf(""),
//...
)
這個方式還可以改成以下的寫法,在建立物件時比較方便
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
/**
* @param initTitle 訓練名稱
* **/
data class TrainingItem(
//...
val initTitle: String = "",
//...
) {
var title by mutableStateOf(initTitle)
}
為了方便處理輸入狀態,這裡先改成OutlinedTextField
,利用 onValueChange
來取得改變後的 title
值,lambda
中的 it
就可以取得編輯後的值。
//Text(
// text = trainingItem.title,
// modifier = Modifier.weight(1f)
//)
OutlinedTextField(
modifier = Modifier.weight(1f),
value = trainingItem.title,
onValueChange = { /*TODO*/ }
)
為了將這個值傳到上層的 Composable,我在 TrainingItem
新增function參數changeTitle: (String) -> Unit
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TrainingItem(
trainingItem: TrainingItem,
changeTitle: (String) -> Unit,
onClick: () -> Unit
) {
}
再把 function
給 OutlinedTextField
用,這樣上層就可以拿到 Title String
onValueChange = { changeTitle(it) }
TrainingItem 藉由 changeTitle 得到 title 就可以使用 viewModel 的 function 還操作
LazyColumn(
modifier = Modifier
.padding(padding)
.padding(horizontal = 8.dp)
) {
itemsIndexed(trainingList) { i, item ->
TrainingItem(
item,
changeTitle = {
trainingVM.updateTrainingTitle(i, it)
},
onClick = { trainingVM.deleteTraining(i) }
)
}
}
一開始我只改了 List 中的 item 的 value
//ViewModel
fun updateTrainingTitle(index: Int, newTitle: String) {
_trainingList[index].title = newTitle
}
畫面上顯示 Ok
但是當我使用複製最後一個item 時卻發現還是取到舊的值
所以就改成直接把整個 TrainingItem 換掉
//ViewModel
fun updateTraining(trainingItem: TrainingItem) {
_trainingList[trainingItem.index] = trainingItem
}
//LazyColumn
TrainingItem(
item,
changeTitle = {
trainingVM.updateTraining(item.copy(initTitle = it))
},
onClick = { trainingVM.deleteTraining(i) }
)
雖然嘗試讓 List 的參數也能有狀態,然而我在複製List的時候卻沒有取得更新後的狀態的值,也許是狀態沒更新?
截稿時間在即,先用置換整個 List Item 來達到更新,未來再繼續研究。
第一次跑鐵人賽,來呼應第一天我的問題:“30天後筆者的身心狀況會怎麼樣呢?”。
這30天體重維持,反而有burn out 的感覺。連續30天維持運動的強度,卻在每天 00:00 前交稿衝刺 (第一天就把存稿用完了每天都在想新東西,反而睡眠不足了,時間管理有待加強啊。
經過這次的挑戰,也發現時間是擠一擠就會出現的東西!?不知不覺每天多了2~3小時的學習時間,也希望這個習慣能和睡眠時間再調整一下,持續在下班時間充實自己。
感謝團員們的支持,有你們才能在每天凌晨之前熱血衝刺。
今日運動
休息(終於可以好好睡覺了XD
上一篇裡,trainingVM
expose 出來的 trainingList
型態是 List<TrainingItem>
List<T>
型態本身不可觀察。Compose 只能觀察 State<T>
的變化來 trigger recomposition。
簡單的改法可能是直將型態改成 SnapshotStateList<T
有關清單的 item 內容更新後,沒有觸發 recomposition 的議題,在這個 codelab 有討論與解決建議,供您參考
Jetpack Compose 的狀態概念說明