在 Compose 中,使用者介面無法變更,即後無法更新
繪製。您可以控制的是 UI 狀態,每當
UI 變更,Compose 會重新建立
已變更。可組合函式可接受
並公開事件,例如 TextField
會接受值並公開
回呼 onValueChange
,要求回呼處理常式變更
值。
var name by remember { mutableStateOf("") }
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = { Text("Name") }
)
由於可組合函式接受狀態並公開事件,因此單向資料流 最適合搭配 Jetpack Compose 使用本指南著重介紹 Compose 的單向資料流模式、如何實作事件及 狀態容器,以及如何在 Compose 中使用 ViewModel。
單向資料流程
單向資料流 (UDF) 是狀態向下流動的設計模式 事件數量和事件都會增加只要跟隨單向資料流,您就能分離 這些可組合函式會在應用程式儲存的部分顯示狀態的 UI 狀態 以及變更狀態
使用單向資料流的應用程式 UI 更新迴圈如下所示:
- 事件:部分 UI 產生事件並向上傳遞,例如 傳遞至 ViewModel 處理的按鈕點選動作;或者是 例如指出使用者工作階段 已過期。
- 更新狀態:事件處理常式可能會變更狀態。
- 顯示狀態:狀態容器向下傳遞狀態,然後在 UI 中顯示。 基礎架構
使用 Jetpack Compose 時遵循這個模式可提供幾個優點:
- 可測試性:從使用者介面分離狀態,更容易 分別進行測試
- 狀態封裝:由於狀態只能在一個位置更新, 可組合函式狀態只會有一個可靠資料來源, 您可能會因為狀態不一致而產生錯誤
- UI 一致性:
使用可觀測的狀態容器,例如
StateFlow
或LiveData
。
Jetpack Compose 的單向資料流
基於狀態和事件的可組合函式運作。舉例來說,TextField
僅
當 value
參數更新且會顯示 onValueChange
時
回呼:要求將值變更為新事件的事件。撰寫
將 State
物件定義為值容器,並變更狀態值
才會觸發重組程序您可以將狀態保留在
remember { mutableStateOf(value) }
或
rememberSaveable { mutableStateOf(value)
,取決於您需要的時間長度
請記住 值
TextField
可組合值的類型為 String
,因此可以
從任何位置存取:透過硬式編碼值、從 ViewModel,或從
父項可組合函式。您不一定要將其保存在 State
物件中,但您需要
,在呼叫 onValueChange
時更新值。
定義可組合函式的參數
定義可組合函式的狀態參數時,應注意下列事項 幾個關鍵問題:
- 可組合項的可重複使用或靈活性如何?
- 狀態參數對這個可組合函式的效能有何影響?
為了鼓勵分離和重複使用,每個可組合項應盡可能減少 資訊例如,建構可組合元件時 新聞文章的標題,最好只傳入 而不是整篇新聞報導:
@Composable
fun Header(title: String, subtitle: String) {
// Recomposes when title or subtitle have changed.
}
@Composable
fun Header(news: News) {
// Recomposes when a new instance of News is passed in.
}
有時候,使用個別參數也可以提升成效,例如
News
包含多個資訊,不只是 title
和 subtitle
,時
新的 News
執行個體會傳遞至 Header(news)
,可組合函式會將
重組。title
subtitle
請仔細考量您傳入的參數數量。讓函式具有 參數過多會降低函式的人體工學,因此在本例中 最好是將這些畫面組合成一個類別
Compose 中的事件
應用程式的所有輸入內容都應以事件表示:輕觸、文字變更、
甚至是計時器或其他最新動態當這些事件變更 UI 狀態時
ViewModel
應該是處理這些程式碼並更新 UI 狀態的那個。
UI 層一律不得變更事件處理常式以外的狀態,因為 可能會在應用程式中造成不一致和錯誤。
最好傳遞狀態和事件處理常式 lambda 的不可變值。這個 的好處如下:
- 提高可重複使用性。
- 請確保 UI 不會直接變更狀態值。
- 避免並行問題,因為您可以確保狀態不會 已從另一個執行緒變動。
- 通常,您可以降低程式碼的複雜度。
舉例來說,接受 String
和 lambda 做為參數的可組合項可以
非常容易重複使用假設熱門應用程式
則應用程式中一律顯示文字並提供返回按鈕。您可以定義
較通用的 MyAppTopAppBar
可組合函式,可接收文字和背面
按鈕控點做為參數:
@Composable
fun MyAppTopAppBar(topAppBarText: String, onBackPressed: () -> Unit) {
TopAppBar(
title = {
Text(
text = topAppBarText,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxSize()
.wrapContentSize(Alignment.Center)
)
},
navigationIcon = {
IconButton(onClick = onBackPressed) {
Icon(
Icons.Filled.ArrowBack,
contentDescription = localizedString
)
}
},
// ...
)
}
範例:ViewModel、狀態和事件
使用 ViewModel
和 mutableStateOf
也可以引入單向資料
流程。
- 系統會透過可觀測的狀態容器 (例如
StateFlow
或LiveData
) 公開 UI 狀態。 ViewModel
會處理來自 UI 或其他應用程式層的事件 並根據事件更新狀態容器。
舉例來說,如要實作登入畫面,請輕觸「登入」按鈕 ,應用程式應會顯示進度旋轉圖示和網路呼叫。如果 登入成功,然後您的應用程式會切換到其他畫面;在 應用程式顯示 Snackbar 錯誤。以下說明如何建立螢幕狀態的模型 以及事件:
畫面共有四種狀態:
- 已登出:使用者尚未登入。
- 進行中:應用程式目前嘗試讓使用者透過 以及執行網路呼叫
- 錯誤:登入時發生錯誤。
- 已登入:使用者已登入。
您可以模擬這些狀態,做為密封類別。ViewModel
會將狀態顯示為
State
、設定初始狀態,並視需要更新狀態。
ViewModel
也會公開 onSignIn()
方法,處理登入事件。
class MyViewModel : ViewModel() {
private val _uiState = mutableStateOf<UiState>(UiState.SignedOut)
val uiState: State<UiState>
get() = _uiState
// ...
}
除了 mutableStateOf
API 之外,Compose 也提供
適用於 LiveData
、Flow
和 的擴充功能
Observable
註冊為事件監聽器並將值顯示為狀態。
class MyViewModel : ViewModel() {
private val _uiState = MutableLiveData<UiState>(UiState.SignedOut)
val uiState: LiveData<UiState>
get() = _uiState
// ...
}
@Composable
fun MyComposable(viewModel: MyViewModel) {
val uiState = viewModel.uiState.observeAsState()
// ...
}
瞭解詳情
如要進一步瞭解 Jetpack Compose 中的架構,請參閱下列資源:
範例
Jetchat is a sample chat app built with Jetpack Compose.
To try out this sample app, use the latest stable version of Android Studio. You can clone this repository or import the project from Android Studio following the steps here.
This sample These samples showcase different architectural approaches to developing Android apps. In its different branches you'll find the same app (a TODO app) implemented with small differences.
In this branch you'll find:
User Interface built with Jetpack Jetnews is a sample news reading app, built with Jetpack Compose. The goal of the sample is to showcase the current UI capabilities of Compose.
To try out this sample app, use the latest stable version of Android Studio. You can clone this repository Learn how this app was designed and built in the design case study, architecture learning journey and modularization learning journey.
This is the repository for the Now in Android app. It is a work in progress 🚧.
Now in Android is a fully functionalJetchat sample
Architecture
Jetnews sample
Now in Android App