Hilt几个重要概念
① 入口点 EntryPoint
Android中 Hilt一共支持6个入口点,分别是:
-
Application
-
Activity
-
Fragment
-
View
-
Service
-
BroadcastReceiver
我理解Hilt注入是整体性的行为,需要一个完整的结构网。那么网的入口首先是Application。基于Application,以各个不同层级的入口点为每一层的起点,开始构建注入结构。
② 组件 Component
我简单的理解:为注入的逻辑实例提供生命周期并限制执行范围的载体。Hilt为Android内置了7种组件,这些组件默认绑定在Android的特定类上(以绑定生命周期和结构层级)。
Component | Scope | 对应Android类 |
---|---|---|
SingletonComponent | @Singleton | Application |
ActivityRetainedComponent | @ActivityRetainedScope | ViewModel |
ActivityComponent | @ActivityScoped | Activity |
FragmentComponent | @FragmentScoped | Fragment |
ViewComponent | @ViewScoped | View |
ViewWithFragmentComponent | @ViewScoped | 带有 @WithFragmentBindings 注释的 View |
ServiceComponent | @ServiceScoped | Service |
我们先说执行范围,上面说了,注入是有层级的结构网,外层对内层是包含关系。每一层注入的逻辑实例是可以允许更内层的网执行的(即注入在SingletonComponent的逻辑实例可以在其他任何组件中执行),但范围也限制了注入逻辑实例在比注入层更外层的组件是无法执行的(如注入在ActivityComponent组件的逻辑实例是不能在SingletonComponent组件中执行的)。官网有张图描述了组件之间的层级关系
下面我们聊一下生命周期
Hilt 会按照相应 Android 类的生命周期自动创建和销毁生成的组件类的实例。
关于组件的默认绑定
每个 Hilt 组件都附带一组默认绑定,Hilt会将组件作为依赖项注入对应的Android类。这些绑定针对的是如Activity或者Fragment等这种基础类型而不是某个子类(我简单的理解为组件绑定的是特定Android类的生命周期和结构层级)Hilt 会使用单个 activity 组件定义来注入所有 activity。每个 activity 都有此组件的不同实例。
③ 作用域 Scope
Scope和Component是一一对应的,使注入的逻辑实例在对应的生命周期中,只存在唯一的实例。
默认情况下,Hilt 中的所有注入的逻辑实例都未限定作用域。这意味着,每当一个组件请求一个逻辑实例注入时,Hilt 都会创建一个新逻辑实例。
在很多情况下,在指定的组件内我只需要注入一个单例的逻辑实例。这就是Scope针对的场景。为注入的逻辑实例指定作用域,在作用域对应的组件生命周期中,始终只存在同一个逻辑实例。
我给一个流管理类A(逻辑类)指定一个Singleton的作用域,那么在此进程运行期间,这个流管理类A将在此进程(SingletonComponent生命周期)中只存在一个实例。
如果我给事件分发类B指定一个ActivityScoped的作用域,那么在同一个Activity(ActivityComponent)的生命周期中,这个事件分发类B只存在一个实例,但在另一个Activity的生命周期中,事件分发类B会被创建一个新的实例。(关于指定ActivityScoped作用域注入ActivityComponent组件的逻辑类在不同的Activity中为不同的实例,我理解是作用域是指定组件的,但组件是绑定Android类的,每个绑定的Android类实例都持有对应组件的不同实例,相应的不同组件实例中的单例逻辑实例也是不同的)