
此系列文章是以我的業餘專案: Kimoji 作為範例。
這款以純 Jetpack Compose 撰寫的 side project,已經在 Google Play 上架。 歡迎試玩!
立馬下載
限免兌換碼
在昨天的文章中無法順利選取標籤的問題,解決方法有兩種:
Label data class 的定義,將 checkedState 的型態從 Boolean 改成 MutableState<Boolean>,這樣可以讓 Compose 觀察 item 的變化。List 中移除這個 item,然後把變動過的 item 重新加入清單,讓 Compose 觀察清單變更內容。這兩種方法各有優缺點。舉例來說,根據 List 實作方式的不同,移除並讀取 element 可能非常耗費資源。
建議避免讓操作 List 消耗太多資源,然後讓 checkedState 可被觀察,這樣做能夠提昇效能,也比較適合 Compose。
新的 Label 看起來可能會像這樣:
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
data class Label(
  val id: Int, 
  val name: String, 
  val checked: MutableState<Boolean> = mutableStateOf(false)
)
我們可以使用 property delegate,讓變數 checked 更加簡潔。
把 Label 從 data class 改成 class。讓 Label 在 constructor 接收 initialChecked 變數,預設值為 false。接下來,我們就能用 mutableStateOf factory method 初始化 checked 變數,並把 initialChecked 當做預設值。
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
data class Label(
  val id: Int, 
  val name: String, 
  initialChecked: Boolean = false
) {
    var checked by mutableStateOf(initialChecked)
}
大功告成!現在「多選標籤」能夠撐過 recomposition 和 configuration changes 了!

因為我們將事務邏輯放進 ViewModel,而不是和 composable functions 耦合,這樣也讓 unit test 更容易進行了。
有興趣的話,可以進一步使用 instrumented test 確認 Compose 程式碼和 UI state 是否都能正常運作。
此系列文章是以我的業餘專案:Kimoji 為範例。
Kimoji 是一款心情日記 App,讓你用可愛的 emoji 來撰寫你的心情日記。現在就來試試這款設計精美的微日記吧!
立馬下載
限免兌換碼
Reference: https://developer.android.com/codelabs/jetpack-compose-state