はじめに
間もなくリリースされると予想される Android Gradle Plugin (AGP) 8.0 から、ライブラリモジュールにおいて R クラスがデフォルトで非推移的になります。本記事では、Non-Transitive R Classes の概要と、マイグレーション手順、導入のメリットについてまとめます。
Non-Transitive R Classes とは
:library2
と :library1
の2つのモジュールがあり、:library2
が :library1
に依存しているとします。従来 R クラスは推移的だったため、:library1
にあるリソースであっても あたかも:library2
にあるリソースであるかのように扱うことができました。
しかしこれにはパフォーマンス上の問題がありました。なぜならビルドをするたびにそのモジュールだけでなく、モジュールが依存するすべてのモジュールのリソース ID も生成する必要があるからです。結果的に実行ファイルのサイズが大きくなり、ビルド時間も長くなっていました。
ここで登場するのが Non-Tansitive R Classes です。名前の通り、R クラスを非推移的にすることで上記の問題を解決することができます。
Non-Transitive R Classes に移行する
Non-Transitive R Classes への移行手順を紹介します。やり方は簡単で、Android Studio でプロジェクトを開き、| Refactor | Migrate to Non-Transitive R Classes... |
を押すだけです。
自動的に android.nonTransitiveRClass=true
追加され、推移的に参照されていたリソースはパッケージ名を含む完全修飾名を使って参照されるようになります。
参考
非常に大きいプロジェクトの場合、Android Studio がフリーズすることがあるようです。その場合はこちらの記事の方法が参考になります。 https://slack.engineering/its-a-non-transitive-r-class-world/
リソースの完全修飾名の解決策
完全修飾名を使用することは煩雑で冗長なため、import alias を使って解決することができます。下記にサンプルコードを示します。
// Before
val bg = com.github.maxfie1d.common.resources.R.drawable.background
// After
import com.github.maxfie1d.common.resources.R as CommonR
val bg = CommonR.drawable.background
注意
Import alias は Kotlin の機能であるため、Java で使用することができません。したがって Java では完全修飾名を使用する必要があります。
ビルド時間の変化
プロジェクトによって異なりますが、Web で調べた限りでは インクリメンタルビルドにおいて 10%~20% 程度のパフォーマンス向上 を期待できるようです。機会があれば、手元のプロジェクトにおいてもパフォーマンス計測してみようと思います。