Jetpack Compose 是一種響應式的 UI 框架,當我們更新 UI 的狀態時,Compose 會自動更新 UI。

為了達成這個目標,Jetpack Compose 使用 State 來記錄與感知 UI 狀態的變化。

State 是一種特別的變數,會隨著 APP 的運行而發生變化,進而改變 UI 的外觀。

程式碼範例

假設我們想要建立一個計數器 (Counter),每按一下,就把 count 這個變數加 1

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            StateLabTheme {
                Column (
                    verticalArrangement = Arrangement.Center,
                    horizontalAlignment = Alignment.CenterHorizontally,
                    modifier = Modifier.fillMaxSize()
                ) {
                    Counter()
                }
            }
        }
    }
}

private var count = 0 // 這不是 state

@Composable
fun Counter() {
    Button(
        onClick = {
            count++
            Log.d("TAG", "count: $count")
        }
    ) {
        Text("Count:  $count")
    }
}

這個 app 有個問題,當我們按下按鈕後,可以在 Logcat 裏看到 count 變數的變化,但是畫面上的數字依舊是 0,不會改變。

這是因為 count 不是 State,所以 Compose UI 不會被通知到 count 這個變數已經改為,需要重畫 (Recompose) UI 畫面。

建立一個 state 變數

我們稍微修改一下程式碼,把 count 改為 state 變數

...

// 這個是 state 變數
private var count = mutableIntStateOf(0)

@Composable
fun Counter() {
    Button(
        onClick = {
            count.intValue++
        }
    ) {
        Text("Count:  ${count.intValue}")
    }
}

...

現在我們再按下按鈕,按鈕上的計數就會隨之改變。

使用 delegate 來簡化程式

加入兩個 import 敘述,我們就可以用 by 語法來簡化程式

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

...

private var count by mutableIntStateOf(0)

@Composable
fun Counter() {
    Button(
        onClick = {
            count++
        }
    ) {
        Text("Count:  $count")
    }
}

...

將 state 移至 composable 中

一般而言,我們不會使用全域變數來存放 state。

有一種比較簡單的方式,是透過 remember 系列的函式,把 state 放在 composable function 中。

這樣當 recompose 時,變數的值才不會因重置而丟失,畢竟它被記住 (remember) 了

...

//private var count by mutableIntStateOf(0)

@Composable
fun Counter() {
    var count by remember {
        mutableIntStateOf(0)
    }
    Button(
        onClick = {
            count++
        }
    ) {
        Text("Count:  $count")
    }
}

...

另一種方式是把 state 移到 ViewModel 中,這個方式其實是比較主流的實作方式,等有機會再討論。

參考資料

https://cloud.tencent.com/developer/article/2198813

Last modified: 2025 年 8 月 6 日

Author

Comments

Write a Reply or Comment

Your email address will not be published.