fresh digitable

めんどくさかったなってことを振り返ったり振り返らなかったりするための記録

fluxとかMVIみたいな構造のアプリを作ってみたかった その4

つづきです: akihito104.hatenablog.com

このツイートに関連して困ったことが起きている。

以前載せたクラス図の左下にNavigationDelegateというクラスがある。

https://user-images.githubusercontent.com/9658489/91858210-d8d6c680-eca3-11ea-802f-bb4a9e01ce2a.png

このNavigationDelegateはandroidxのNavControllerを持っており、ViewStatesで行った処理の結果を受けて画面遷移を行う。また、NavControllerのOnDestinationChangedListenerを介して現在のNavHostFragmentの変更通知を受け取り、これを監視可能な形でViewStatesに提供している。

NavigationDelegateはDIからActivityをコンストラクタインジェクションされ、必要になった時にActivityからNavControllerを取り出している。クラス図を見てわかる通り、NavigationDelegateは間接的にViewModelの持ち物になっている。これが問題で、Activityの再生成が起きるとき、NavigationDelegateが弱参照で持っているActivityは無くなって参照できなくなるのでNavigationDelegateごと作り変える必要があるのだが、ViewModelはActivityのライフサイクルを超えて再利用されるのでNavigationDelegateの再生成は行われない。

思いつく解決策としては次の三つ。

  • ViewModelをやめる: 根本的な解決策だがすべてのデータ管理を確認する必要がありちょっと大変。
  • ApplicationLivecycleCallbacks経由で新しいActivityを受け取れるようにする: Activityを注入する代わりにApplicationLivecycleCallbacksを実装しているクラスを注入して常に最新のActivityインスタンスを参照できるようにする。既存のコードはあんまり変えなくてよさそうだけどうまくいくのかよくわからん。
  • NavigationDelegateはActivityに持たせて、ViewStatesから発行されたナビゲーションに関するイベントを待ち受ける。NavHostの状態はRepositoryとかに適当に突っ込む。よう知らんけどAndroidアプリらしいような気がする。

2020/11/01 解決策についていくらか追記した。