配合分支:day24/start,Repo: 按我
覺得怪嗎?那個人怎麼可以在那個地方,做那件事?察覺到了嗎?難不成那件事情違反了資料流?說的沒錯,資料流的確出了問題。
我說的就是這裡:

注意到了嗎?ViewModel 裡頭的資料怎麼在 ComposeView 修改了呢?這裡需要調整一下封裝,將更新某一則照片日記這件事,包裝成一個 setter。像這樣將 property 直接暴露出來不太好,不然隔壁的陳先生也可以隨時來修改。
狀態(State)更新很重要,盡量在 ViewModel 裡頭做更動未來也比較好追查。
仔細想,更新一篇照片日記會需要什麼資料呢?
在課程的前期有提到怎麼知道是同一篇日記? (如果忘記了,記得往前看。) 每次日記生成時,會設定這則日記的唯一 id,用這個 id 來查就能查到同一篇了。
所以這裡,需要 id。
簡單,在前面的課程之中已經將心情調整成 enum class,可以直接當成變數傳進來。
總結上述,這個 function 需要:updateMood(id: String, mood: Mood)
取得 id 去查哪一篇日記,需要更新成傳進來的心情。
先將日記變成一個 private property 以防忘記關門。
var entries by mutableStateOf(loadInitialEntries())
private set // 👈🏼 改成只有 private 能 set
接下來直接將 ComposeView 那一段程式碼接回 ViewModel 內部。
在那之前,之前漏掉介紹 map 這個 Kotlin collection 的內建 Function (也叫 API)。map 可以將吃進去的值,一個一個在 {} 內進行變化後吐回去。例如:
var numbers = listOf(1, 2, 3, 4) // 👈🏼 [1, 2, 3, 4] 的列表
numbers = numbers.map { number -> // 👈🏼 一個一個丟出來
number * 2 // 👈🏼 最後一行會回傳,這邊將每一個值都 * 2
}
// 最後 numbers = [2, 4, 6, 8]
弄懂 map 在幹嘛之後,這個 Function 就比較容易看懂:

剛剛已經把 entries 關起來了,現在 PhotoDiaryApp 應該會開始抱怨啦。調整這邊結束後,今天的收尾就完成囉:
onMoodChange = { diaryId, selectedMood ->
// 👇🏼 改由 ViewModel 修改即可
viewModel.updateMood(diaryId, selectedMood)
}