配合分支:day09/start,Repo: 按我
必須增加刪除日記的功能,以防暗黑照寫入日記後需要刪掉。今天來簡單粗暴的把每一張照片日記卡片加入「刪除」按鈕。大概像這樣:

加⋯加入按鈕,簡單!來思考流程會怎麼跑。

List<DiaryEntry> 列表,裏面裝著 DiaryEntry。List<DiaryEntry> 該把哪個照片移除掉,需要把位置傳回去entries 來自於 ViewModel,所以 ViewModel 要提供一個方法來刪照片位置從過去 5 天常駐之處開始下手 PhotoDiaryApp。顯示照片日記列表,就從 DiaryList 開始下手。日記在 LazyColumn 之處,藉由一個一個取出 entries ,再慢慢塞 DiaryCard 到畫面上。

簡單粗暴做了按鈕,並將「刪除」按鈕按下去的事件,做成一個 Callback Function。做好之後,在 LazyColumn 用到的地方,就會開始 panic!說需要多一個 callback function。
LazyColumn 除了 items 也有 itemsIndexed (文件) 這個函式可以使用,在印的過程之中,會把現在的 Index (索引,就是現在位置的數值,通常直接講 Index)。可以改成這個,然後把 Index 往回傳。

最後回到最上面的 PhotoDiaryApp,來處理這個 Callback Function。讀到這裡是不是越來越有資料流的感覺了呢?

更新 DiaryList 被呼叫的地方,補上 onDeleteDiary Callback。先用大括弧 {} 展開就好。ViewModel 還什麼都沒有,需要去把真正的「刪除」補上。

這邊很簡單,請開啟 PhotoDiaryViewModel,加入一個新的 Method 給外面的人用。這裡需要說明一下為何 entries.toMutableList() 要有 toMutableList()。
因為 List<DiaryEntry> 是一個 List,裡頭的元素是不能修改的。(我是指 List 順序,或者刪除一個東西,加入一個東西。不是只某一個內容,不能被改),所以先轉成可以被修改的版本,透過index 給 removeAt() 來移除某個位置的元素,再把這個調整後的版本塞回去。
最後,只需要把外面 UI 的 Callback 接上 ViewModel 行為即可。
onDeleteDiary = { displayIndex -> viewModel.deleteDiaryAt(displayIndex) }

配合分支:day09/index-delete,Repo: 按我
效果很讚耶!我有個大膽的想法,何不也把排序做出來呢?拍照的日期,和新增日記的日期可以不同。來做一個排序是用拍照的順序由新到舊排序,好像也挺讚的!

根據簡單粗暴流的做法,「新增日記」的按鈕下加入新的排序按鈕。和「新增日記」表單出現的情形類似,需要用一個狀態 (State) 來控制現在按鈕要顯示什麼文字,這個狀態也會被拿來判斷按下按鈕後的行為。
新增狀態 isNewestFirst。
這個狀態不能因為旋轉而失效,要加入到 ViewModel 之中(有不明白,請參考 Day 08)。

然後,根據這個狀態來回傳列表。因為需要排序不能再讓 UI 直接去取 property。

來介紹一個讚的 Kotlin 內建的 function:sortedByDescending ,照著後方 { } 最後回傳的東西為基礎,倒著排。(由大到小)
這邊透過每一則 diaryEntry 的建立時間 createdAt 由大到小排列,在 Android 裡頭,離現在比較近的日子數值越大。藉由此就可以排列出由近到遠的效果。
現來調整日記列表頁面,這一頁頂端要加上「改變排序的按鈕」,要有一個狀態作為依據(不然不知道顯示什麼文字)。

這一段完成後,就可以回去呼叫 DiaryList 之處,把資料流全部串起來。

到此,一切就完成啦!來看看成果如何:

重新排序後,的確是照拍照時間排囉!不過好像有點怪怪的,照時間排之後,按刪除居然刪錯照片了⋯⋯
List<DiaryEntry> 移除哪一張,必須把這個位置帶回去。LazyColumn 除了 items 還能用它,印卡片時一併給出目前 Index,才能把位置塞進刪除 Callback。DiaryCard 的按鈕一路回到 DiaryList、PhotoDiaryApp,再交給 ViewModel;刪除是把事件往上傳,不是在畫面當場改資料。List<DiaryEntry> 不能刪、不能改順序;所以先 toMutableList() 變成可以動手的版本。removeAt() 拿掉某個位置的元素,再把調整後的列表塞回 ViewModel。entries,要由 ViewModel 提供刪除方法,UI 的 Callback 再接上去。{ } 回傳的值由大到小排;本章用 createdAt 排出由近到遠。