マルチモジュールにおいて問題になりがちなのが、画面遷移です。
あるmoduleから、別のmoduleに遷移するときにどのようにするのが良いのかが悩ましい問題かと思います。
ぼくのなかではNavigation Componentを使うことで色々解決できると思っています。
Navigation Graph
NavigationではNavigation Graphという画面遷移を定義したXMLを作成します。
このXML内にFragmentやActivityのクラスを記述するのですが、実はこのクラスはビルド時に参照できるかをチェックしていません。
そのため、モジュールを跨いだ定義が可能になります。
Navigationでは画面遷移は基本的にリフレクションを使ってるため、もし間違っている値を設定してる場合は実行時エラーになります。
モジュール間の画面遷移
上記で書いたように、クラスが参照できるかをチェックしてないため、モジュール間の画面遷移を定義することが可能になります。
まず、Navigation Graphは各モジュールの共通のモジュール(例えばcoreモジュール)等に配置します。
Navigation GraphではXMLを直接書くことで、参照できないクラスでも指定することが可能です。
参照できないクラスは以下のように赤字になりますが、ビルドは可能です。
あとは普通にNavigation Componentを使うだけです。
SafeArgs
遷移元のモジュールにXMLを定義してしまうと、遷移先のモジュールからSageArgsのコードが参照できなくなるので、元と先とで共通で参照できるモジュールに定義する必要があります。
coreモジュールのほうでXMLを定義すると別のモジュールでも参照できるので、SafeArgsも普通に使えます。
apply plugin: "androidx.navigation.safeargs.kotlin"
のプラグイン指定もcoreモジュールだけで大丈夫です。
デメリット
いくつかデメリットがあります。
- GUIでFragment/Activityを選択できない(XML自体そんなに難しくないので問題ないかも)
- XMLの赤字が気になる
- ActivityからActivityの遷移など、Navigationが使いにくい箇所がある(そもそものNavigationの問題)
Dynamic Feature Moduleの課題
追記: 2.1.0-alpha02でクラッシュしなくなりました。b/124538597
On-demandなDynamic Feature Moduleを使う場合は、注意が必要です。
(これを書いてるときは 1.0.0-beta02
なので、それが前提です)
Navigation GraphのXMLを読み込むときに、 <activity>
だけはクラスの存在チェックが行われています。(Fragmentはチェックされない)
そのため、ダウンロード前のモジュールのActivityへの遷移を定義しているXMLを読み込んだ時点でクラッシュします。
現状で良い回避方法は思いついてはないですが…
( ActivityNavigator
をカスタマイズすればいけるかな?)