查看原文
其他

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

Android Android 开发者 2021-08-05

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 可以直接使用。


  • 多绑定
    https://dagger.dev/dev-guide/multibindings.html

@HiltViewModelclass PlayViewModel @Inject constructor( val db: MusicDatabase,) : ViewModel() { ... }
@AndroidEntryPointclass PlayActivity : AppCompatActivity() {
val viewModel: PlayViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle) { super.onCreate(bundle) viewModel.play() }}


✅ 支持测试 API



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


  • 大量的工作
    https://developer.android.google.cn/training/dependency-injection/dagger-android#dagger-testing

  • Hilt 的实现方式
    https://developer.android.google.cn/training/dependency-injection/hilt-testing


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


  • @UninstallModules
    https://developer.android.google.cn/training/dependency-injection/hilt-testing#replace-binding

  • @BindValue
    https://developer.android.google.cn/training/dependency-injection/hilt-testing#binding-new

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



✅ 良好的一致性



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


  • Dagger 基础知识
    https://developer.android.google.cn/training/dependency-injection/dagger-basics


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


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



✅ 支持自定义组件



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

https://medium.com/androiddevelopers/hilt-adding-components-to-the-hierarchy-96f207d6d92d


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


  • @InstallIn
    https://developer.android.google.cn/training/dependency-injection/hilt-android#hilt-modules


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



✅ 支持 Dagger 和 Hilt 交互



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

https://developer.android.google.cn/codelabs/android-dagger-to-hilt#0


❌ 不支持组件依赖



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


  • 相关文档
    https://dagger.dev/hilt/subcomponents-vs-deps


在大多数项目中,将 Dagger 迁移到 Hilt 是值得的。Hilt 给您带来的收益超出了更新所需付出的努力。我们提供了很多资源来助力迁移,请参阅:
  • 详细的迁移文档
    https://dagger.dev/hilt/migration-guide
  • Codelab | 从 Dagger 迁移到 Hilt
    https://developer.android.google.cn/codelabs/android-dagger-to-hilt
  • Google I/O 应用迁移到 Hilt 的博客和代码提交记录
    • 文章 
      https://medium.com/androiddevelopers/migrating-the-google-i-o-app-to-hilt-f3edf03affe5
    • 代码提交记录

      https://github.com/google/iosched/commit/9c20fdd52d446e5fdb03369e50fb196c31ae16e3

  • Hilt 和 AssistedInject 协同使用要点

    https://gist.github.com/manuelvicnt/437668cda3a891d347e134b1de29aee1


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



 点击屏末 | 阅读原文 | 即刻了解更多关于使用 Hilt 实现依赖项注入



推荐阅读

如页面未加载,请刷新重试


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存