ユニファ開発者ブログ

ユニファ株式会社プロダクトデベロップメント本部メンバーによるブログです。

Jetpack Compose でUI StateとViewModelを使った状態管理

こんにちは、Androidエンジニアのジャズニーです。

最近になってようやく本格的にJetpack Composeに取り組んでみようと決意して、色々と勉強したり試したりしているなかで、状態管理という重要な問題の対応方法について調べていて、色々なやり方ある中、自分の中で一番しっくりきた方法の知見をまとめてみました。

まえおき

この状態管理の仕方についてはAndroid公式を読んで参考にした書き方になっています。

よく見かけるUI Stateの管理方法

UI Stateの管理方法について調べている中で最も多く見かけた方法が、ViewModelにFlowなどで状態をこんな感じで書く方法が多かったです。

このような書き方だと、簡単な画面構造やデータを表示するだけの場合にはすごくシンプルで分かりやすいので問題ないのですが、普段の実装では逆に使いにくいのではないかと考えています。
なぜならUIの状態というのはかなり多くの情報の複雑な組み合わせでできているからです。例えば、画面の全項目を非表示にしてローディングだけを表示させたり、特定の項目は非表示だけどそうでない項目は表示させたり、画面が複雑化して項目が増えればViewModelでの定義も増やさなくてはいけなり、ViewModelがとんどん複雑化していきます。

UI StateとViewModel

前述の書き方だとViewModelがどんどん複雑化していってしまうので、オブジェクト指向を応用して、UI Stateに関係するコードを全て一つのクラスに書き出します。
先ほどのコードを書き直すと簡な感じになります。

そして、このUI StateのクラスをViewModelではこのように使用します。

この書き方を行ったときに気をつけたいのが、UI Stateを更新するときには必ずcopy を使用することです、なぜならFlowを更新するときに新しいオブジェクトが必要になるのですが、毎回新しく生成してしまうと今現在表示している状態を失ってしまうので、コピーをベースに変更点のみ更新する必要があります。 

この状態のコードを画面で使用する時はこんな感じになります。

まとめ

この方法を応用すれば、UI Stateのクラス一つに状態がまとまって管理がしやすくなると思います。 今回は簡単なローディングをJetpack Composeを使った例ですが、この方法はJetpack Composeだけではなく従来のXMLを使用したコードでも使用できます。
例のコードはないですが、イベントに関しては、ユーザーイベントは作成したUI Stateのdata classに追加して使用しますが、消費型のUIイベント(画面遷移やSnackBarの表示など)に関しては、専用のクラスで対応した方がupdateをするたびに値が流れるということがないのでよりシンプルになります。

ユニファではプロダクトを一緒に創っていく仲間を募集しています!

unifa-e.com