在 Composable functions 裡,如果有 state 會由多個函式讀取或修改,就應該放在 common ancestor 裡面,這個過程稱為「state hoisting」。「hoist」的意思就是「抬高」或「提高」。
此系列文章是以我的業餘專案: Kimoji 作為範例。
這款以純 Jetpack Compose 撰寫的 side project,已經在 Google Play 上架。 歡迎試玩!
立馬下載 索取兌換碼
藉由 state hoisting,可以避免因為有太多重複的 state 而產生 bug,也可以讓我們更能重複利用 composables,還能讓 composables 更容易進行測試。而相反地,如果有 state 不需要由 composable 的 parent 管理,則我們就不應該 hoist 這些 state。簡單來說,Source of truth 屬於建立和管理 state 的人。
舉個例子,我們可以在 app 裡建立一個 onboarding 畫面。
在 MainActivity.kt
加入以下程式碼:
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.foundation.layout.Arrangement
...
@Composable
fun OnboardingScreen() {
// TODO: This state should be hoisted
var shouldShowOnboarding by remember { mutableStateOf(true) }
Surface {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(R.drawable.joy),
contentDescription = null,
modifier = Modifier
.padding(vertical = 24.dp)
.size(40.dp)
.clip(CircleShape)
)
Text("Welcome to the Kimoji!")
Button(
modifier = Modifier.padding(vertical = 24.dp),
onClick = { shouldShowOnboarding = false }
) {
Text("Hi, Kimoji!")
}
}
}
}
@Preview(showBackground = true, widthDp = 320, heightDp = 320)
@Composable
fun OnboardingPreview() {
KimojiTheme {
OnboardingScreen()
}
}
我們來看看這段程式碼裡面的功能:
OnboardingScreen
的 composable 以及新的預覽畫面。如果我們 build project,就會發現同時會出現多個預覽畫面。我們也在 preview 加入了固定的寬高,以便檢查內容是否可以正確對齊。shouldShowOnboarding
使用的是 by
keyword,而不是 =
。這是 property delegate,讓我們可以不用每次都打 .value
來存取 state。shouldShowOnboarding
會設為 false
,但是我們還沒有從任何地方讀取這個 state。明天我們會繼續在 app 裡加入 onboarding 畫面。目標是在啟動 app 時顯示此畫面,並在使用者按下「Hi, Kimoji」 之後隱藏畫面。
此系列文章是以我的業餘專案:Kimoji 為範例。
Kimoji 是一款心情日記 App,讓你用可愛的 emoji 來撰寫你的心情日記。現在就來試試這款設計精美的微日記吧!
立馬下載 索取兌換碼
Reference: https://developer.android.com/codelabs/jetpack-compose-basics