將 data 和 event 遷移到 ViewModel
此系列文章是以我的業餘專案: Kimoji 為範例。
這款以純 Jetpack Compose 撰寫的 side project,已經在 Google Play 上架。 歡迎試玩!
📥 立馬下載 | | | 🎟️ 限免兌換碼
延續昨天的文章,今天我們來把 UI 狀態 (也就是日記清單) 搬到 ViewModel,然後開始抽出事務邏輯。
- 建立檔案
DiaryViewModel.kt
,並定義 ViewModel class。
把「資料來源」getDiaries()
移到 DiaryViewModel
。
定義 _diaries
內部變數,透過前兩天文章介紹的方法,使用 toMutableStateList
來指定初值,然後曝露 diaries
日記清單,讓它的值只能透過 ViewModel 來變更。
我們使用 List
內建的 remove
函式,來實作簡單的刪除功能。
2. 我們可以藉由呼叫 viewModel()
函式,從任何 composable 來存取這個 ViewModel
。
如果要使用這個函式,開啟 app/build.gradle
檔案並加入以下 library,然後在 Android Studio sync dependencies:
3. 開啟 DiaryScreen
。新增 diaryViewModel
當做DiaryScreen
composable 的參數,並呼叫 viewModel()
來初始化 ViewModel instance。這樣的介面設計,有助於在測試這個 composable 時抽換 ViewModel
,並可在需要時 hoist state holder。接著,我們將「日記清單」和「刪除函式」傳給 Journal
composable,並移除我們之前定義的 onDelete
lambda 函式。
viewModel()
會傳回現有的 ViewModel
或在指定 scope 內建立新的 ViewModel。只要 scope 還存續著,系統就會保留 ViewModel 的 instance。例如,如果在 Activity
中使用 composable,viewModel()
會傳回相同的 instance,直到 Activity
finish 或 kill process 為止。
我們已經把畫面上一部分狀態和事務邏輯與 ViewModel
整合。由於狀態會保留在 Composition 之外,並由 ViewModel
儲存,因此對「日記清單」的變動就可以撐過 configuration changes 了。
ViewModel
無法在所有情況下自動維持 app 的狀態 (例如系統觸發的 process death)。如果想詳細瞭解如何維持 app 的 UI 狀態,可以參閱說明文件。
ViewModel
適合被引用在畫面層級的 composable,「畫面層級的 composable」代表它較為靠近從Activity
、Fragment
或 Navigation graph destination 呼叫的 root composable。ViewModel
不應向下傳遞給其他 composable,而應該只往下傳遞需要的資料,以及執行必要邏輯的函式。如果想深入瞭解,請參閱 ViewModel 和 state holder,以及官方的 Compose and other libraries 說明文件。
此系列文章是以我的業餘專案: Kimoji 為範例
Kimoji 是一款心情日記 App,讓你用可愛的 emoji 來撰寫你的心情日記。現在就來試試這款設計精美的微日記吧!
📥 立馬下載 | | | 🎟️ 限免兌換碼