Dagger HiltのenableExperimentalClasspathAggregationオプションについて

少し前の話題ですが、取り上げている記事が見当たらなかったためまとめます。

前提

Androidプロジェクトにおいて3つのモジュールが以下のような依存関係にあったとします。

app -> intermediate -> db

appモジュールはApplicationクラスを持ち、モジュール間の依存関係はimplementationで記述されているとします。

このとき、マルチモジュールの利点の1つとして、
appモジュールがdbモジュールに直接依存していないことによって、dbモジュール内のコードを直接参照することを防ぐことができます。 … (1)

問題

Dagger Hiltではルートのappモジュールにおいて全てのインスタンスを生成するためにそれらに直接参照できる必要があります。

つまりDagger Hiltを利用しようとすると、
appモジュールがdbモジュールに直接依存するか、intermediateモジュール内でdbモジュールへの依存関係をapiで定義する必要があります。 … (2)

これだと先ほどのマルチモジュールの利点 (1) が失われてしまいます。

github.com

解決策

この問題のワークアラウンドとして、Dagger Hilt 2.31.x-alpha以降からappモジュールの build.gradle ファイルに以下のような記述をすれば (2) の対応を行わずとも (1) の利点を保つことができるようになります。

hilt {
    enableExperimentalClasspathAggregation = true
}

ただし、まだExperimentalです。

詳しくはこちら dagger.dev

ざっとしかコードを読んでいないのですが、遷移的依存関係をコンパイル時に利用できるように CompileOnly コンフィグを利用して依存関係を処理しているようです。

https://github.com/google/dagger/pull/2154/files#diff-074bfa3b2e7f8ced706b26436ee5ae320b798417cae69aa14b50a348fec73712R169-R195

このような処理を行っているので、ビルド時処理が増えてしまいます。

これに関しては、以下のように述べられているので今後改善していくと思われます。

This solution is inefficient and will cause build performance impact, but it is a starting point that can be further optimized by using a smarter transform that can extract the necessary classes required by Dagger and Hilt.

github.com

おまけ

この問題はHiltに限った話でなく、Daggerでも発生します。

github.com

幸いなことにDagger 2.29で追加された validateTransitiveComponentDependencies オプションを利用すると解消されるようです。

これに関して解説しているページを見つけたので添付しておきます。

https://www.notion.so/Dagger-2-29-validateTransitiveComponentDependencies-ca18f5d15cc14ed1a92426f935ea32e0