UI 状態の分割アイデア

前置き 結論 実装例 UI 状態の定義 UI 状態の内部に保持する各データクラスの定義 各 StateFlow の定義 combine 関数で UI 状態を生成する ポイント 4 つの UI 状態に制限したこと どんなプロパティでも UI 状態に定義した 4 つのプロパティにだいたい収まる まとめ 前置き Jetpack Compose では、一つの画面で、 UI 状態を一つだけ定義しておくことが一般的かと思います。 画面が複雑になっていき、 UI のプロパティが増えていくと、 combine 関数で Flow を合成できなくなることがあります。 これは、 combine 関数の引数が最大でも 5 であるため、それよりたくさんの Flow を直接 combine することができないためです。 そのような場合の一つの対応案のここに残します。 結論 UI 状態のプロパティを以下の 4 つのプロパティにまとめます (制限します) 。 UI ローカル状態 フォーム入力状態 派生 UI 状態 非同期取得データ これらをすべて StateFlow で定義し、データの変更を監視します。 データの変更が検出されるたびに、 combine 関数で StateFlow 内の実データを UI 状態のプロパティにセットします。 ...

2026年6月9日 · 3 分 · 奥田 智紘

Boolean に潰された「状態」

Boolean に潰された「成功」 ― リファクタリングで気づいた抽象化の罠 はじめに 元のコード リファクタリングでやったこと 最初は「うっかり」だと思った 本当の原因 抽象化の粒度が粗すぎた 型で守る設計 学び 終わりに Boolean に潰された「成功」 ― リファクタリングで気づいた抽象化の罠 はじめに ViewModel の保存処理をリファクタリングしていたとき、 私は一度コードを壊しました。 原因は単純な「うっかりミス」に見えました。 しかし振り返ってみると、問題はもっと深いところにありました。 それは、 「成功」という概念を Boolean に潰してしまったこと でした。 この記事では、その過程と学びを書きます。 元のコード 保存処理は、新規作成と更新で分岐していました。 private fun saveData() { viewModelScope.launch { val isExistingItem: Boolean = (取得) if (destId == 0) { // 新規作成 val resultSuccess = directDebitDefRepo.createDestination(...) if (resultSuccess) { // フォームの初期化 _formInputState.update { FormInputState() } showSuccess() } else { showFailure() } } else { // 更新 val resultSuccess = directDebitDefRepo.updateDestination(...) if (resultSuccess) { showSuccess() } else { showFailure() } } } } ポイントはここです。 ...

2026年3月4日 · 2 分 · 奥田 智紘