
Jetpack Compose が普及した今でも、「View と State を分離することは重要ですか?」という質問をよく見かけます。
結論から言うと、重要ではあるものの、設計の中心ではなくなりました。
Compose が登場したことで、私たちが考えるべきことは「View と State を分離すること」から、「State をどこに持つべきか」へと変わっています。
🤔 XML 時代は「View と State の分離」が重要だった
従来の Android View システムでは、View は変更可能なオブジェクトでした。
画面を更新するたびに、
- setText()
- setVisibility()
- notifyDataSetChanged()
のような API を呼び出して View を直接変更します。
State
│
ViewModel
│
View(XML)
View が多くの状態を抱えていたため、UI の更新処理とビジネスロジックを分離することが、保守性を高めるために非常に重要でした。
🤔 Compose は View 自体が状態を持たない
Compose では UI は関数です。
@Composable
fun UserScreen(state: UserState) {
Text(state.name)
}
state が変われば、Compose が自動的に再コンポーズし、UI を描き直します。
開発者が View を直接更新することはほとんどありません。
つまり、
State
│
Composable
│
UI
という流れになり、「View をどう更新するか」を意識する場面は大幅に減りました。
その結果、「View と State を分離すること」自体の重要性は相対的に小さくなっています。
🤔 公式ドキュメントが強調しているのは State Hoisting
Compose の公式ドキュメントを見ると、「View と State の分離」ではなく State Hoisting が中心テーマになっています。
最初に紹介される原則がこちらです。
State は、それを利用する場所のできるだけ近くに置くべき
これは XML 時代の
「まず ViewModel に置こう」
という発想とは少し異なります。
例えば、1つの Composable だけが利用する状態なら、
var expanded by rememberSaveable {
mutableStateOf(false)
}
のように Composable の中で保持することが推奨されています。
公式ドキュメントでも、
Keeping UI element state internal to composable functions is acceptable.
と明記されています。
🤔 ViewModel は「すべての State の置き場所」ではない
Compose の公式ドキュメントには、さらに興味深い説明があります。
The lowest common ancestor can also be outside of the Composition. For example, when hoisting state in a ViewModel because business logic is involved.
ここで重要なのは、
「ビジネスロジックが関係するから ViewModel に置く」
と説明していることです。
「画面の State はすべて ViewModel に置く」とは書かれていません。
さらに、公式は ViewModel を次のようにも説明しています。
A ViewModel is just an implementation detail of a state holder with certain responsibilities.
つまり ViewModel は、
State Holder の実装方法の一つ
という位置付けです。
もちろん、ViewModel は今でも重要なコンポーネントです。
しかし、Compose の世界では「唯一の State Holder」ではありません。
🤔 Compose では「State の寿命」を考える
Compose では State の種類ごとに、適切な置き場所があります。
UIだけで使うState
│
remember
│
rememberSaveable
│
Navigation
│
ViewModel
│
Repository
それぞれ保持できる期間が異なります。
- remember は再コンポーズまで
- rememberSaveable は Configuration Changes や Process Death 後まで
- Navigation は画面遷移に関する状態
- ViewModel は画面のライフサイクルとビジネスロジック
- Repository はアプリ全体のデータ
Compose では、
「この State は ViewModel に置くべきか?」
ではなく、
「この State はどのくらい生き続けるべきか?」
という視点で考える方が自然です。
🤔 まとめ
Compose によって、「View と State を分離する」という考え方が間違いになったわけではありません。
ただし、Compose は UI 自体が宣言的になったため、その問題は以前ほど大きくなくなりました。
現在の Android アーキテクチャで重要なのは、
「State をどこに配置するか」
そして
「その State をどのライフサイクルまで保持するか」
です。
実際、Compose の公式ドキュメントも「View と State の分離」ではなく、「State Hoisting」や「State Ownership」を中心に説明しています。
ViewModel を使うことが目的ではなく、State に最適な寿命と責務を与えることが、Compose 時代の設計と言えるでしょう。
🤔 参考
Related Categories : Android・Developmemt・JetpackCompose・KMP・Kotlin・Kotlin Multiplatform Mobile・Recommended