从 Dagger 迁移到 Hilt 可带来的收益

从 Dagger 迁移到 Hilt 可带来的收益

Hilt 发布于 2020 年 6 月,为 Android 提供了依赖项注入 (DI) 的标准化方案。对于新项目,Hilt 有着编译期校验,良好的运行时性能以及扩展性 (阅读文章 Android 和 Hilt 中限定作用域,获取更多信息)。然而,Hilt 对于已经使用 Dagger 的应用有何优势呢?您是否应该将现有的应用迁移到 Hilt 呢?以下几点阐述了您的团队需要投入精力到迁移工作中的原因。

✅ 支持 AndroidX 扩展

如果您已经使用 Dagger 处理 ViewModel 或者 WorkManager,您就会知道,注入您自己的 ViewModelFactory 与 WorkerFactory 需要大量的模板代码,并且需要 Dagger 相关知识。最常见的实现就是使用 多绑定,这是 Dagger 中最复杂的功能之一,开发人员往往难以理解。Hilt 通过移除模板代码大大简化了 AndroidX 的使用。更妙的是,您甚至无需对 Android Framework 的类注入 Factory,就好像没有使用 Hilt 一样。通过使用 @HiltViewModel,Hilt 为您创建了正确的 ViewModelProvider.Factory,正因如此,被 @AndroidEntryPoint 注解的 Activity 和 Fragment 可以直接使用。

@HiltViewModel
class PlayViewModel @Inject constructor(
  val db: MusicDatabase,
) : ViewModel() { ... }

@AndroidEntryPoint
class PlayActivity : AppCompatActivity() {

  val viewModel: PlayViewModel by viewModels()
  
  override fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(bundle)
    viewModel.play()
  }
}

✅ 支持测试 API

DI (依赖项注入) 本应该使测试更加容易,但讽刺的是,使用 Dagger 进行测试需要 大量的工作。实际上,您必须同时维护正式和测试的 Dagger 关系图,而 Hilt 的实现方式 则更加便捷。

Hilt 测试可以使用 @UninstallModules 功能显式修改 DI 关系图。除此之外,还提供了诸如 @BindValue 一类的其他功能,可以轻松地将测试字段绑定到 DI 关系图中。

@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class ExampleTest {

  @get:Rule
  var hiltRule = HiltAndroidRule(this)
  
  @BindValue @JvmField
  val analyticsRepository = FakeAnalyticsRepository()
  
  @Test 
  fun myTest() { ... }
}

✅ 良好的一致性

在 Dagger 中有很多种方法可以实现相同的功能。由于早期缺乏 Android 应用的指南文档 (去年我们已经解决了这一问题,例如指南文章: Dagger 基础知识),导致社区中出现许多争论,最终造成了不同开发者在 Android 应用中使用和配置 Dagger 的方式不一致。

您可能会存在异议,认为迁移到 Hilt 是不值得的,因为当前的 Dagger 配置已经非常完善,并且您完全掌握 Dagger 的工作原理以及所有依赖项是如何被注入的。这对您个人来说可能是正确的,但是您是否考虑过团队的其他成员 (包括潜在的未来同事)?您是否能确保切换至新项目时仍能正常运作?了解 Dagger 在应用中的配置和使用是一项艰巨且耗时的工作。

通过在应用中使用 Hilt,上述工作量将会显著减少,因为所有 Hilt 应用都使用相同的配置。新加入团队的开发者不会对 Hilt 的配置感到困惑,因为这和他们之前的配置方式几乎相同。

✅ 支持自定义组件

除了已经定义的标准组件之外,Hilt 也提供了创建自定义组件并添加到组件层次结构中的方法,详见文章 Hilt — 添加组件到层次结构

虽然自定义组件降低了一致性,但是这会给您带来很大收益!自定义组件也可以配合模块自动发现功能 (@InstallIn 注解功能) 以及测试替换功能一起使用。

但是,自定义组件和 Hilt 内置组件的区别在于,这些组件无法自动注入到 Android Framework 的类中 (即 @AndroidEntryPoint 的功能)。

✅ 支持 Dagger 和 Hilt 交互

Hilt 和 Dagger 可以共存!如果允许 Hilt 接管 SingletonComponent,则可以在应用中某些部分使用 Hilt 的特性,并从中受益,而其他特殊部分仍保留 Dagger。这同样意味着可以 逐步完成向 Hilt 的迁移

❌ 不支持组件依赖

Hilt 的易用意味着它代替您做出了一些决定。Hilt 在组件关系中采用了子组件模式,您可以查看 相关文档 了解这样设计的原因。如果您坚信您的应用更适合采用组件依赖,那么 Hilt 就不是您应用的正确选择。

在大多数项目中,将 Dagger 迁移到 Hilt 是值得的。Hilt 给您带来的收益超出了更新所需付出的努力。我们提供了很多资源来助力迁移,请参阅:

如果您有任何问题,或者您需要更多相关信息,请在文章下方留言反馈。

版权声明

禁止一切形式的转载-禁止商用-禁止衍生 申请授权

脉脉不得语
脉脉不得语
Zhengzhou Website
Android Developer | https://androiddevtools.cn and https://androidweekly.io WebMaster | GDG Zhengzhou Funder & Ex Organizer | http://Toast.show(∞) Podcast Host

你已经成功订阅到 Android 开发技术周报
太棒了!接下来,完成检验以获得全部访问权限 Android 开发技术周报
欢迎回来!你已经成功登录了。
Unable to sign you in. Please try again.
成功!您的帐户已完全激活,您现在可以访问所有内容。
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.