Photo by Lisa Luminaire on Unsplash Androidの公式ドキュメントにある設計ガイド が更新され、実装について以前よりだいぶ明確に指針が記載されています。
その中で、ViewModelからのイベントで画面にメッセージを表示するような消費型のイベントについての記載があります。
https://developer.android.com/jetpack/guide/ui-layer/events#consuming-trigger-updates
イベントも状態として表現しており、メッセージ等を表示後にその状態を更新するような感じの処理になります。
個人的にずっと悩んでた、SingleLiveEvent は推奨されないけどどう実装するのが良いのだろう…っていう悩みが解決しました。
ただ、ガイドでは簡略されてるため実際にこのパターンで実装するうえでの悩みと実際にどう実装すれば良いかを考えてみました。
実装の悩みどころ 設計ガイドの実装では Snackbar でメッセージを表示するようになっていますが、現実ではそれ以外にも処理したいことがあります。
例えば、何か処理が終わって成功したときに画面遷移をしたい場合にどう実装するのが良いのか。
メッセージを表示する手段も、 Snackbar だけじゃなく AlertDialog や Toast もあります。
この複数の種類があるイベント処理についてどう実装するのが良いのかが悩みどころです。
これをどう解決するかを考えてみました。
UIの処理パターンで状態を分ける 例えば、以下のような感じで、UIでの処理パターンを状態としてUI Stateで別々で管理する方法です。
更にViewModel側でこれらのイベントを消費するメソッドを用意してあげます。実装例は省略してますが、それぞれ処理済みのイベントListを除外してUI Stateを更新する感じです。
ViewModelからイベントを発行するには以下のような感じです。
UI側はそれぞれで対応する処理をする感じです。以下の例はComposeを想定していますが、Viewシステムで似たような感じになります。
実装としてはこれでも問題なく実現できるかなぁとは思いますが、だいぶ冗長な感じがしています。UIの処理パターンが増えるたびに管理する状態も増えていきます。
また、ViewModelからイベントを発行する際にUIの処理を強く意識する必要があります。
イベントを1つの状態で管理する ぼくが考えたもう一つの実装方法として、イベントを1つの状態として管理する方法です。
まず、ViewModelから発生するイベントを sealed interface/class
で定義し、UI Stateで管理します。この例では成功とエラーの2種類を定義しています。
次にイベント処理後に消費するためのメソッドを追加します。単純にイベントListから消費したいイベントを除外したListを作成してUI Stateを更新する感じですね。