目次
<li>
<a href="#i-5">終わり</a>
</li>
前置き#
ちは、saikiです。
DataBindingについて調べてたら、
「MVVMにしたかったのでNavitagorInterfaceを使いました、詳しくはAndroidアプリ設計パターン入門をみてね。」
みたいな記事を見つけて、へーと思いながら読んでみた(買ってあったので)んですがむしろMVVMとしてはよろしくなさそうで、AACのViewModelやLiveDataが一般的になった今ではそっちを使った方法を取るほうが良いかもねという話です。
一年前の本ではありますが未だに買われているイメージがあるので。
どう書かれているか#
本の中ではTODOアプリをMVVMで作る例が説明されています。
TaskDetailNavigatorとは
・必要となるタスクに対するアクションを定義しているインターフェイスです。詳細画面では削除と編集画面への遷移が該当します
TaskDetailViewModel の setNavigator メソッドで TaskDetailNavigator を受け取り、mTaskDetailNavigator に保存しています。deleteTask メソッドや startEditTaskメソッドでは単純に Navigator を呼び出しているだけです。
ViewModelがメンバにNavigatorを持つようです。
Navigator はインターフェイスですので利用には実装済みのインスタンスが必要です。本プロジェクトの MVVM パターンではアクティビティがその役割を果たします。
mTaskDetailNavigator は実際にはアクティビティ(TaskDetailActivity)への参照です。
何がよろしくなさそうか#
説明とサンプルコードを見る限りNavigatorはActivityが実装し、ViewModelがその参照を持ちます。
そして最後の引用のこの部分。
mTaskDetailNavigator は実際にはアクティビティ(TaskDetailActivity)への参照です。
とのことなんですが、この本でも説明されている通り、MVVMはViewへの参照を持つべきではないはずです。
ViewModel は View へのアクセスに必要な参照を持たないため ViewModel から直接 View を更新できません(自動的な更新に任せます)。
MVP アーキテクチャでは Presenter から View を更新できます。View に必要な参照があるためです。変更が必要な場合は、Presenter から明示的に View を呼び出して更新できます。
なのでViewModelがActivityの参照を持つのは基本的にはやめたほうがいいでしょうと。
そこの部分だけMVPみたいだなと。
確かにgoogleSampleもこの通りに作られているんですがこのサンプル自体、最終更新が二年前になっているので今とはだいぶ状況が違うように思います。
じゃあどうすんのさ?#
これに関しては同じくgooglesampleのmasterかtodo-mvvm-live-kotlinを参考にするのが良さそうです。(masterブランチはAACやコルーチンが使われていますがDaggarが使われていないのでとてもみやすくてサンプルとしてあまりにも優秀)
masterの場合#
masterブランチではNavigatorInterfaceは存在せず、 **Navigation component**を使って画面遷移をしています。
FragmentがViewModelのLiveDataをObserveし、通知が来ればNavigationを使って画面遷移をするという流れです。
自然だし、ViewModelがViewへの参照も持ちません。とても今風ですね。
todo-mvvm-live-kotlinの場合#
こちらは少し古いせいか、NavigationComponentが使われていません。NavigatorInterfaceを実装しています。
ただ、ViewModelは参照を持たず、AcgtivityがViewModelのLiveDataをObserveし、通知が来ればNavigatorInterfaceのメソッドを呼びます(自身に実装されているので自分のメソッドを呼ぶのと代わりない見た目になっていますが)。
こちらもViewModelがViewの参照を持っていません。
=================================
NavigationComponentを利用しているのであればmasterを、そうでなければtodo-mvvm-live-kotlinを参考にすると良さそうです。
終わり#
ということで、一年経つと実装もだいぶ変わるんだなあという話でした。
あとgooglesampleはめちゃくちゃ参考になるなあと改めて思いました。
今までAdapterにアイテムクリックのリスナーをActivityやfragmentから渡していたんですが、sampleのようにViewModelを渡してバインディングするとその必要もなくなってすごくいいですね…
とか
意外とFragmentからactivity.findViewById呼ぶんだな…
とか。
そのうちsample周りで自分が知らんかったこともまとめようと思います。
ではまた。
Android 設計パターン入門 自体はわかりやすいのでオススメです。