1、概览
什么是依赖项注入(DI)?
类通常需要引用其他类。通过以下三种方式获取所需的对象:
- 类构造其所需的依赖项。如
Car类
将创建并初始化自己的Engine
实例。 - 从其他地方抓取。某些 Android API(如
Context
getter 和getSystemService()
)的工作原理便是如此。 - 以参数形式提供。应用可以在构造类时提供这些依赖项,或者将这些依赖项传入需要各个依赖项的函数。如
Car
构造函数将接收Engine
作为参数。
第三种方式就是依赖项注入!即以参数形式获取依赖项的方式。
依赖项注入(DI)具有以下优势:
- 使用类能重用及分离依赖项。依赖项的改变,不需要更改使用类。
- 轻松测试。根据测试场景,可以传入不同的依赖项实现以测试所有不同用例。
Android两种主要的依赖项注入方式
-
构造函数注入。这就是上面描述的方式。您将某个类的依赖项传入其构造函数。
-
字段注入(或 setter 注入)。某些 Android 框架类(如 Activity 和 Fragment)由系统实例化,因此无法进行构造函数注入。使用字段注入时,依赖项将在创建类后实例化。
依赖项注入原理
基于控制反转原则,根据该原则,通用代码控制特定代码的执行。
自动依赖项注入
由于手动创建依赖项注入存在多个问题:
-
对于大型应用,获取所有依赖项并正确连接它们可能需要大量样板代码。在多层架构中,要为顶层创建一个对象,必须提供其下层的所有依赖项。例如,要制造一辆真车,可能需要引擎、传动装置、底盘以及其他部件;而要制造引擎,则需要汽缸和火花塞。
-
如果您无法在传入依赖项之前构造依赖项(例如,当使用延迟初始化或将对象作用域限定为应用流时),则需要编写并维护管理内存中依赖项生命周期的自定义容器(或依赖关系图)。
通过自动执行创建和提供依赖项的过程解决此手动创建依赖项的问题。它们归为两类:
-
基于反射的解决方案,可在运行时连接依赖项。
-
静态解决方案,可生成在编译时连接依赖项的代码。
Dagger 是适用于 Java、Kotlin 和 Android 的热门依赖项注入库,由 Google 进行维护。Dagger 为您创建和管理依赖关系图,从而便于您在应用中使用 DI。它提供了完全静态和编译时依赖项,解决了基于反射的解决方案(如 Guice)的诸多开发和性能问题。
2、Android自动依赖项注入方式
Android中有两种自动依赖项注入方式:Hilt和Dagger 2。官方推荐使用Hilt。
Hilt 在依赖项注入库 Dagger 的基础上构建而成,提供了一种将 Dagger 纳入 Android 应用的标准方法。
关于 Dagger,Hilt 的目标如下:
- 简化 Android 应用的 Dagger 相关基础架构。
- 创建一组标准的组件和作用域,以简化设置、提高可读性以及在应用之间共享代码。
- 提供一种简单的方法来为各种构建类型(如测试、调试或发布)配置不同的绑定。
由于 Android 操作系统会实例化它自己的许多框架类,因此在 Android 应用中使用 Dagger 要求您编写大量的样板。Hilt 可减少在 Android 应用中使用 Dagger 所涉及的样板代码。Hilt 会自动生成并提供以下各项:
- 用于将 Android 框架类与 Dagger 集成的组件 - 您不必手动创建。
- 作用域注释 - 与 Hilt 自动生成的组件一起使用。
- 预定义的绑定 - 表示 Android 类,如
Application
或Activity
。 - 预定义的限定符 - 表示
@ApplicationContext
和@ActivityContext
。
Dagger 和 Hilt 代码可以共存于同一代码库中。不过,在大多数情况下,最好使用 Hilt 管理您在 Android 上对 Dagger 的所有使用。如需将使用 Dagger 的项目迁移到 Hilt,请参阅迁移指南和“将 Dagger 应用迁移到 Hilt”Codelab。
2.1 Dagger 2
@Inject
注入,在构造函数可以注入使用@Inject
如果不能在构造函数注入,执行以下操作:
- 使用
@Binds
告知 Dagger 接口应采用哪种实现。 - 使用
@Provides
告知 Dagger 如何提供您的项目所不具备的类。
@Component
会让 Dagger 生成一个容器,其中应包含满足其提供的类型所需的所有依赖项。,Dagger提供依赖关系图,提供使用
作用域注释
@Singleton
单例
2.2 Hilt
Hilt 是推荐用于在 Android 中实现依赖项注入的 Jetpack 库。Hilt 通过为项目中的每个 Android 类提供容器并自动为您管理其生命周期,定义了一种在应用中执行 DI 的标准方法。Hilt 在热门 DI 库 Dagger 的基础上构建而成,因而能够受益于 Dagger 提供的编译时正确性、运行时性能、可伸缩性和 Android Studio 支持。