マルチモジュールの遷移について考える Part1

Androidのトレンドの1つにマルチモジュール構成があります。 マルチモジュールによるメリットとして、

などがあります。大規模なプロジェクトでは上記のメリットは大きいため、マルチモジュールに移行していくことになると思います。

この記事は、マルチモジュールにした際のActivity間の遷移について考えたいと思います。目指すゴールとしては、

Part1では、遷移専用のモジュールを作る方法を考えてみます。

サンプルコード: satoshun-android-example/MultiActivityRouterExample

遷移専用のモジュールを作る

まず依存関係の構築の原則に、Circular Dependency、循環依存を作り出してはいけないというものがあります。

例えば、メイン画面とサブ画面の2画面があり、それらの画面は相互に行き来するとします。それらをメイン画面モジュール、サブ画面モジュールとして切り出すと次のようになります。



これでは循環参照になり、依存関係が壊れてしまうので駄目です。そこでDIP、依存関係逆転の原則を用います。 直接Activityを参照しているのが問題なので、各画面に遷移できる遷移用のインターフェースを定義することで解決を目指します。

そこで、

の2つのモジュールを作ります。

メインルーターモジュールでは次の遷移専用インターフェースを定義します。

interface MainRouter {
  fun routeToMain(context: Context): Intent
}

そして、メインモジュールで実装します。また、今回はDaggerを使って依存を解決します。

internal class MainRouterImpl @Inject constructor() : MainRouter {
  override fun routeToMain(context: Context): Intent {
    return Intent(context, MainActivity::class.java)
  }
}

---

@Module
internal interface MainActivityModule {
  @Binds fun bindMainRouter(impl: MainRouterImpl): MainRouter
}

これで、使う側であるサブ画面は、メインモジュールに依存するのではなく、メインルーターモジュールに依存し遷移することが出来ます。

class SubActivity : AppCompatActivity() {
  @Inject lateinit var router: MainRouter

  ...
}

最終的な依存図は次のようになります。



これで、相互に遷移する画面だとしても循環参照になることなく解決することが出来ます😃

補足

いちいちルーターモジュールを作るのがめんどうなのであれば、共通のRouterインターフェースを作る方法もあります。

interface Router<T> {
  fun route(context: Context, params: T): Intent
}

実装は次のようになります。

---実装

internal class MainRouter2Impl @Inject constructor() : Router<Unit> {
  override fun route(context: Context, params: Unit): Intent {
    return Intent(context, MainActivity::class.java)
  }
}

---Daggerの設定

@Module
internal interface MainActivityModule {
  @Named("main")
  @Binds fun bindMain2Router(impl: MainRouter2Impl): Router<Unit>
}

---使用側

class SubActivity : AppCompatActivity() {
  @field:[Inject Named("main")] lateinit var router: Router<Unit>
  ...
}

DaggerのNamedアノテーションと組み合わせることでいい感じに共通Routerを作ることが出来ます。

まとめ

Part2ではDeeplinkやnavigationを絡めた遷移の方法について考えてみたいと思います😃

サンプルコード: satoshun-android-example/MultiActivityRouterExample

Written by