iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0

說到底,其實所有應用程式的背後都跟資料有關。而 UI 的功能,就是將資料「呈現」給使用者看,或是讓使用者可以「操作」資料。所以 UI 往往不只是「靜態」的畫面,更是「動態」的互動過程。而這些 UI 上可以看得到的變化,底層改變的其實都是資料,而這些不斷變化的資料就是 UI 的「狀態」。

筆者總開玩笑說 UI 是細緻手工業的原因,不只是因為刻出好看的 UI 很難,在以往的 UI 開發裡,開發者總要花費大量的精力去「維護」UI 的狀態,稍有疏漏就會發生 UI 顯示不一致,或是資料沒正確更新等錯誤。換句話說,UI 的狀態管理一直是件苦差事。

在經歷眾多開發範式的更迭後,Compose 在設計上集各家大成,漂亮的解決了這個問題,讓 UI 開發變得更容易了。今天的耕讀筆記就要來研究 Compose 的狀態管理。

狀態管理的基本精神

Compose 狀態管理有幾個重要的基本精神,只要抓到這些概念,在實作時會更容易掌握其精髓:

單向資料流(Unidirectional data flow)

在實作時,儘量讓資料和 UI 是分開的,也就是說 UI 只描述如何繪製畫面、資料就是值的容器。與此同時,UI 也會訂閱(或說觀察)資料的狀態。 所以當 UI 綁定事件時,Event Handler 只要更新資料的值,UI 就會自動收到值更新的通知,再觸發 UI 重繪即可。探句話說,資料就是所謂的 Single source of truth,資料的流動是單向的。聽起來很受限,但開發時反而更簡單。

儘量無狀態(Stateless)

在實作 Compose 元件時,儘量讓元件本身是無狀態的,也就是說用來改變狀態的資料儘量是從外部透過參數傳入,而整個 UI 畫面就可以透過參數傳遞,依照資料改變的狀態來重新繪製畫面,達到 UI 更新的效果。

狀態管理實務

那當我們要管理 UI 的狀態時,Compose 是怎麼做的呢?

儲存狀態

Compose 提供了一個好用的 mutableStateOf() 函式,將預設值傳入函式後,存入變數裡,再將變數傳給元件即可。而在儲存變數時,Compose 提供了三種語法:

  1. 使用等號回傳

    val counter = mutableStateOf(0)
    

    透過型別推斷,counter 內的型別為 MutableState<Int>,若要取出其中的值就要用 counter.value

  2. 使用解構

    val (counter, setCounter) = mutableStateOf(0) 
    

    上面的語法透過解構將 MutableState<Int> 裡的 value 取出成 counter,同時也將更新 counter 時需要的 setCounter() 取出。

  3. 使用屬性代理

    var counter by mutableStateOf(0) 
    

    若將等號(=)改成 by,這時對 counter 的讀寫就會用 getValue()setValue() 兩個方法。不過在使用時,IDE 有時會漏掉 import,可以手動新增:

    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.setValue
    

記住狀態

雖然 mutableStateOf() 函式可以儲存狀態,但每當元件因為狀態改變重繪時,這個狀態也會因此被重設。Compose 提供了 remember {} 語法,用它包住 mutableStateOf() 後,Compose 在重繪元件時,會先「記住」先前的狀態,並在重繪時還原。

以上兩個語法互相搭配,造就了 Compose 簡潔且好維護的狀態管理機制。


上一篇
第 20 天:解析 Modifier
下一篇
第 22 天:佈景主題
系列文
傳教士的 Compose for Desktop 耕讀筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言