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

**URL:** <https://meta.101.dev/t/dagger-hilt/364>\
**Category:** Android 开发\
**Tags:** android, hilt\
**Created:** [2021 年6 月 21 日 07:06 UTC](https://meta.101.dev/t/dagger-hilt/364 "2021-06-21T07:06:26Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![101](https://meta.101.dev/user_avatar/meta.101.dev/101/32/575_2.png) [@101](https://meta.101.dev/u/101)\
**Post date:** [2021 年6 月 21 日 07:06 UTC](https://meta.101.dev/t/dagger-hilt/364/1 "2021-06-21T07:06:26Z")

</div>

![](https://devrel.andfun.cn/devrel/posts/2021/06/Axlbvh.png)

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

**✅ 支持 AndroidX 扩展**

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

```Kotlin
@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 进行测试需要 [大量的工作](https://developer.android.google.cn/training/dependency-injection/dagger-android#dagger-testing)。实际上，您必须同时维护正式和测试的 Dagger 关系图，而 [Hilt 的实现方式](https://developer.android.google.cn/training/dependency-injection/hilt-testing) 则更加便捷。

Hilt 测试可以使用 [@UninstallModules](https://developer.android.google.cn/training/dependency-injection/hilt-testing#replace-binding) 功能显式修改 DI 关系图。除此之外，还提供了诸如 [@BindValue](https://developer.android.google.cn/training/dependency-injection/hilt-testing#binding-new) 一类的其他功能，可以轻松地将测试字段绑定到 DI 关系图中。

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

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

```

## **✅ 良好的一致性**

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

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

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

## **✅ 支持自定义组件**

除了已经定义的标准组件之外，Hilt 也提供了创建自定义组件并添加到组件层次结构中的方法，详见文章 [Hilt — 添加组件到层次结构](https://medium.com/androiddevelopers/hilt-adding-components-to-the-hierarchy-96f207d6d92d)。

虽然自定义组件降低了一致性，但是这会给您带来很大收益！自定义组件也可以配合模块自动发现功能 ([@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 在组件关系中采用了子组件模式，您可以查看 [相关文档](https://dagger.dev/hilt/subcomponents-vs-deps) 了解这样设计的原因。如果您坚信您的应用更适合采用组件依赖，那么 Hilt 就不是您应用的正确选择。

在大多数项目中，将 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)

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