はじめに
Android開発では、「戻るボタン」が押された際に画面状態に応じて処理を切り替える場面が頻繁にあります。例えば、
- 条件Aのときはダイアログを表示して確認を促す
- 条件Bのときは確認なしに画面を終了する
- 条件Cのときは何も処理を行わない
などのシナリオです。
シンプルなケースであれば問題ありませんが、状態の組み合わせが増えてくるとif文が増え、コードの見通しが悪くなります。
今回は、このような状況でイベント送信パターンを導入し、責務を明確に分離することでコードの可読性と保守性を改善した事例を紹介します。
Before:Viewで直接状態を管理した場合の問題点
以下はよくある実装例です。
override fun onBackPressed() {
if (!isDialogVisible && isDataAvailable) {
showDialog()
} else if (!isDataAvailable) {
finish()
}
}
このコードの課題点
- 画面の状態(isDialogVisibleやisDataAvailable)がView側に直接書かれているため、Viewが状態を把握・管理する必要があり、責務が曖昧になる
- 状態のパターンが増えるほど、if分岐が複雑になり、可読性が低下する
- 後々の変更に弱く、保守しづらい
After:イベント送信パターンで責務を分離したコード
イベント送信パターンを導入すると、コードは次のように改善できます。
ViewModel側で状態に基づいたイベントを発行
fun handleBackPressed() {
val event = when {
shouldShowDialog -> UiEvent.ShowDialog
shouldCloseScreen -> UiEvent.CloseScreen
else -> null
}
event?.let(::sendEvent)
}
状態は以下のようにシンプルに整理できます。
val shouldShowDialog = !isDialogVisible && isDataAvailable
val shouldCloseScreen = !isDataAvailable
View側はイベントを受け取って処理を行うだけ
viewModel.eventFlow.collect { event ->
when (event) {
UiEvent.ShowDialog -> showDialog()
UiEvent.CloseScreen -> finish()
}
}
- ViewModelが画面の状態を判断し、具体的な処理はイベントとして通知
- Viewはイベントを受け取り、それに応じた処理を実行するのみでよい
こうすることで、ViewとViewModelがそれぞれの役割に集中でき、コードの可読性が飛躍的に向上します。
Afterの改善ポイントまとめ
改善前 | 改善後 |
---|---|
Viewが状態を直接管理 | 状態管理はViewModelが担当 |
状態と具体的な処理が混在 | Viewは受け取ったイベントに反応するだけ |
状態が増えるとコードが複雑化 | イベント送信するだけになりシンプルを保てる |
イベント送信パターンを取り入れるメリット
- 責務が明確に分離され、ViewはUI処理に専念、ViewModelはロジックと状態管理に専念できる
- イベントの送信処理を一箇所にまとめることで、変更に強いコードになる
- 新しい状態や処理が追加されたときも、自然に拡張可能になる
ぜひ試してみてください!!!