非传递R类
#android #性能 #gradle #build

在升级我的Android项目使用AGP 8.0.0时,我注意到Android Build Analyzer建议使用非交易式R类来提高构建速度。

Build Analyzer Recommendation

我很想知道它是什么以及它的工作原理。所以,我做了一些研究,这就是我发现的。

为什么

非传播R类已经存在了一段时间,但默认情况下没有启用。使用AGP 8.0.0,默认情况下启用了它。对于好奇的头脑,我提供了一个博客,该博客讨论了本文结尾处的R类和非传播R类的历史。

非传播R类启用每个库类的命名课程,以便其R类仅包含在库本身中声明的资源,而在库的依赖项中没有任何资源,从而降低了R类的大小对于那个库。

例如,如果代码使用来自androidx.navigation:navigation-ui-ktx依赖项的默认动画R.anim.nav_default_enter_anim。在不使用非传播R类的情况下,模块的“ R”类具有引用其自己的资源和对导航UI库资源的传递引用。

  import com.learning.compose.R
  ...

    .setStartAnimations(activity, R.anim.nav_default_enter_anim, R.anim.nav_default_exit_anim)

启用了非传递R类,这将迫使我们使用完全合格的R类名称访问依赖项模块中的资源,从而减少“ Compose”模块的“ R”类中的引用。而且,通过使用完全合格的R类名称引用,不必重新编译组合模块并提高了构建速度。

  .setStartAnimations(activity, androidx.navigation.ui.R.anim.nav_default_enter_anim, androidx.navigation.ui.R.anim.nav_default_exit_anim)

由于依赖性通过非传播R类变得更加明确,因此代码的模块化增加了。由于资源不能来自传递依赖性,因此它也会降低复杂性。它还可以提高构建速度( clean 增量),如Android Developers from Android Dev Summit '21所承诺的。

该怎么办

如果您使用来自另一个依赖关系/模块的资源,

  • 如果您的Android项目仅100%Kotlin,那么您很幸运。您可以alias导入r类依赖项模块以访问该模块中的资源。
  • 如果您的项目有一些Java代码参考,则必须使用完全合格的R类名称才能访问依赖项模块中的资源

另外,如果您使用另一个模块中的资源,但是您不声明对该模块的依赖性,并且不想声明依赖关系,则可以简单地在App Module中复制资源

怎么做

使用Android Studio的Refactor -> Migrate to non-transitive R classes迁移该项目以使用非传播R类

  • 这将是

    • 在gradle.properties中添加以下内容
    android.nonTransitiveRClass=true
    
    • 更新完全合格的R类名称,无论其在哪里找到非传播R类用法
      .setStartAnimations(activity, androidx.navigation.ui.R.anim.nav_default_enter_anim, androidx.navigation.ui.R.anim.nav_default_exit_anim)
    

此外,如果代码库在Kotlin中

  import androidx.navigation.ui.R as NavUiR

  ...
    .setStartAnimations(activity, NavUiR.anim.nav_default_enter_anim, NavUiR.anim.nav_default_exit_anim)
    .setExitAnimations(activity, NavUiR.anim.nav_default_pop_enter_anim, NavUiR.anim.nav_default_pop_exit_anim)

这是我发现有用的文章的一些引用