Google の公式 Android ガイダンスは 2026年5月18日に更新され、ViewModel のイベントを UI State に変換することを明示的に推奨するようになった

これは、もはや単なる昔からのアーキテクチャ論争ではありません。
Google の Android ドキュメントは 2026年5月18日 に更新され、現在では明確に次のように述べています。
ViewModel events should always result in a UI state update.
ViewModel のイベントは、常に UI State の更新につながるべきです。
これは、ViewModel と UI の間の通信をどのように考えるべきかという点で、大きな変化です。
これまで Android では、次のようなパターンが一般的でした。
ViewModel
│
├── UiState
│
└── UiEvent
↓
UI
UiEvent は、Snackbar の表示、画面遷移、ダイアログの表示など、一度だけ実行したい処理によく使われていました。
しかし現在のガイダンスは、次の方向へ移りつつあります
ViewModel
│
│ UI State
↓
UI
ここでは、簡単な Snackbar の例を使って、この違いを見てみましょう。
🤔 Event-Driven アプローチ
従来の実装は、例えば次のようになります。
sealed interface UiEvent {
data class ShowSnackbar(
val message: String
) : UiEvent
}
private val _events = Channel<UiEvent>()
val events = _events.receiveAsFlow()
fun save() {
viewModelScope.launch {
repository.save()
_events.send(
UiEvent.ShowSnackbar("Saved successfully")
)
}
}
UI 側では、このイベントを消費します。
LaunchedEffect(Unit) {
viewModel.events.collect { event ->
when (event) {
is UiEvent.ShowSnackbar ->
snackbarHostState.showSnackbar(event.message)
}
}
}
この場合、ViewModel は実質的に UI に対して次のように指示しています。
"Snackbar を表示してください。"
これが Event-Driven なアプローチです。
🤔 State-Driven アプローチ
現在の Android ガイダンスは、上記とは異なる方向を示しています。
ShowSnackbar を送るのではなく、ViewModel が UI State を更新します。
data class UiState(
val userMessage: String? = null
)
fun save() {
viewModelScope.launch {
repository.save()
_uiState.update {
it.copy(
userMessage = "Saved successfully"
)
}
}
}
UI は State を監視します。
LaunchedEffect(uiState.userMessage) {
uiState.userMessage?.let { message ->
snackbarHostState.showSnackbar(message)
viewModel.userMessageShown()
}
}
この場合、ViewModel は次のように言っているわけではありません。
"Snackbar を表示してください。"
代わりに、次のように伝えています。
"現在、表示すべきメッセージがあります。"
どのように表示するのかは UI が決定します。
🤔 重要な違い
この違いは、単純に
Channel → StateFlow
という API の置き換えではありません。
本質的には次の違いです。
Event-Driven:
ViewModel
↓
"これを実行して"
↓
UI
State-Driven:
ViewModel
↓
"これが現在の状態です"
↓
UI
Google は、この違いを次のようにも表現しています。
「State は存在する。Events は発生する。」
もちろん、イベントそのものがなくなったわけではありません。
ボタンのクリックは、今でもイベントです。
User
↓
Button.onClick
↓
ViewModel
↓
State
↓
UI
重要な変化は、ViewModel → UI の通信が、一度きりのイベントではなく State を中心とする方向へ進んでいることです。
🤔 では、Event を使うのをやめるべきなのか?
公式ガイダンスは、Channel、SharedFlow、あるいはイベントそのものを禁止しているわけではありません。
むしろ、ViewModel のイベントを UI State として表現できないかを改めて考えることを求めています。
ViewModel を設計するときには、次の問いが役立ちます。
- ViewModel は UI に「何をすべきか」を伝える必要があるのか?
- 「現在何が起きているのか」を State として表現するだけでよいのか?
この小さな考え方の変化が、Android の UI アーキテクチャの設計を大きく変える可能性があります。
🤔 参考
Related Categories : Developmemt・Google・JetpackCompose・KMP・Kotlin・Kotlin Multiplatform Mobile・Recommended・Trending