Compose での ViewModel と状態
Compose での ViewModel と状態
ちょっとだけすすめる。とりあえず、githubからcloneしてビルド完了するまでは確認できた。
ちょっと触ったけど、TextFieldに入力しても消えるのは修正させるためのバグ?
4. アプリ アーキテクチャの詳細
モデル駆動型 UI
UseCase
とか Repository
から作る(=Model層)のがいいよという話。アプリのライフサイクルやコンポーネントとの関連が低いので、ここから実装すればUI側を実装する時にそれを呼び出すだけでよく嬉しい。的な。
あとは、例えばiOSエンジニアがAndroidにシフトした時に、まずはModel層から開発すれば純粋なKotlinだけを扱えてシフトがスムーズになる。(という所感)
5. ViewModel を追加する
タイトルの通り。
画面が表示する要素や、要素がタップされた時などの制御を実装しておく領域として、ViewModelを追加しそこに内包させる。
で、それにあたって、 StateFlow
というクラスを使うみたい。
private
には MutableStateFlow
を定義しておいて、外だしするものには StateFlow
として定義しておく。その時に MutableStateFlow.asStateFlow()
で、参照させておく。(インスタンスとして別モノを見ることにはならないのかな。。。)
6. Compose UI を設計する
最初の onValueChange
のくだりは、双方向データバインディングの話かな。
単方向データフロー
は、ViewとViewModelの関係性。ViewModelがViewからのイベントを受け取って、それを処理する。処理した結果状態が変わるなら、それをViewModelが検知してそれに合わせた表示に変わる。
入力欄に何を入力してもクリアされるのは、やはり修正させるためのバグだったのか。
でも、入力欄のテキストを毎回ViewModelが受け取ると、その度にリコンポーズが走ってそうでちょっともやっとするなぁ。
7. 推測した単語を照合して、スコアを更新する
check***
という関数名は嫌だなぁ。
ドメイン知識がある人ならいいけど、そうじゃない人なら
「おおん?チェックって具体的に何するんだ?」ってなるよな。
今回はなさそうだけど、それで 真偽値を返すものならもう「それなら is****
にしろよ!」って思っちゃう。
あーなるほど。結果を真偽値で管理するけど、Uiに通知が必要だから UiStateに持たせるのか。
でも結局↑で思ったことは解消されないわ
8. スコアと単語カウントを更新する
今度はスコアを更新する処理。こちらはViewModelからの一方向だから、TextFieldの入力を受け取っていたさっきよりも単純。
9. ゲームの最終ラウンドを処理する
ゲームの終了契機の制御。ダイアログを表示してユーザに結果を通知する。
ダイアログなので、既存の画面に乗せる形で表示するので、Compose関数の最後に条件分岐を追加してダイアログのコンポーサブルを画面に追加する。
10. デバイスの回転の状態
ここではコードを修正することは特になく、 ViewModel
を利用することによって 画面回転など Activity
の破棄・再生成が行われた時にも、 ViewModel
オブジェクトは自動的に保持され、再生成後も同様に利用できることを確認している。
画面回転だけではなく、テーマ変更(ライト/ダーク)やフォントサイズ変更を契機にも破棄・再生成は行われるから、画面回転に対応しないアプリであってもこの機能はすごく重要なんだよな。
というわけで、このCodeLabは以上。
- ViewModelの情報を Viewに参照させるときは StateFlow を使う。特にViewModel内で値を更新する必要があるため、privateでは MutableStateFlow、外出し向けには これを asStateFlow() で StateFlow 型に変換したものを参照させる。
- 状態を更新する時には object.copy() を使って再代入をしてあげれば、リコンポーズを促せるしデータは同じ内容だしで嬉しい。
ということが勉強になった。