2023-05-08-Dagger使用
IOC及依赖注入
IOC: Inversion Of Control
DI: Dependency Inject
Mode of Injection:
- Constructor Injection: Injecting the method parameters.
- Field Injection: Injecting the member variable (must not be private).
- Method Injection: Injecting the method parameter.
A dependency consumer asks for the dependency(Object) from a dependency provider through a connector.
- Dependency provider: Classes annotated with
@Module
are responsible for providing objects which can be injected. Such classes define methods annotated with@Provides
. The returned objects from these methods are available for dependency injection. - Dependency consumer: The
@Inject
annotation is used to define a dependency. - Connecting consumer and producer: A
@Component
annotated interface defines the connection between the provider of objects (modules) and the objects which express a dependency. The class for this connection is generated by the Dagger.
上面的意思就是,要使用依赖注入,需要有三个元素组成。
- 依赖生产者,也就是我们用
@Module
标注的Module类 - 依赖关系消费者,使用
@Inject
用于定义依赖关系 - 连接消费者和生产者,也就是我们的
@Component
,在我们使用Dagger时,我们只需要定义接口,具体的类实现Dagger会帮我们实现
依赖
implementation 'com.google.dagger:dagger-android:2.46' |
简单使用
构造方法注入
构建一个User实体类,在构造方法上使用@Inject注解
public class User { |
构造Component
,定义inject方法,参数选择需要注入的Activity
|
使用: 在Activity中需要执行注入动作
public class MainActivity extends AppCompatActivity { |
使用Modules提供对象实例
- 创建Module,命名规则一般为 XXXModule
|
- 在Component中添加module
|
- 使用方法和用构造方法注入一样
Dagger作用域限定
- 使用作用域限定,可以
将某个对象的生命周期限定为其组件的生命周期
。这样也就意味着,在作用范围内,使用到的是同一实例
。 @Singleton
是Dagger提供的一种默认的作用域注解
,其意义表示一个单例对象。也就是实例的生命周期和程序运行的生命周期保持一致。- 使用
@Scope实现自定义作用域注解
。 - 作用域注解使用在@Inject、@Provides、@Binds、@Module、@Component注解上,表示其产生作用的范围。
第一点的意思,举个例子,如果我们在上面的Module中,将Retrofit 和 ApiService 都标注为@Singleton
,我们也需要在其装载的组件,也就是ApplicationComponent
中限定生命周期。
|
|
我们可以看一下Singleton的完整代码
|
可以看到,当然,这里也不一定要使用@Singleton,可以自定义任何的注解。
在上面的例子中,我们的Retrofit
和ApiService
都指定了相同的作用域,在其装载的组件ApplicationComponent
,也指定了相同的作用域,也就是在ApplicationComponent
组件的作用范围内,获取到的Retrofit
都是统一对象
作用域和单例是两个不同的概念
@Singleton是Dagger提供的一种作用域实现
作用域就是用来管理Component来获取对象实例的生命周期的。
使用作用域遵循的一些规则
- 在没有必要的情况下,尽量使用默认的作用域,即不指定作用域。
- 使用作用域注解的模块也只能在带有相同作用域注解的组件中使用。
- 作用域的指定,必须是上层对下层兼并的关系,这里把上下级分为三层:@Inject/@Provides/@Binds为第二层,@Module为一层,@Component为第三层。如果在上层指定了作用域,那么下层的作用域要么不指定,一旦指定只能保持和上层一致。
- 开发设计时,一定要有清晰的依赖图,不然很容易产生依赖死循环。
组件依赖
重新为组件设置Module实例
存在这样的场景,需要重新设置Module实例:
- 模块类中定义了一些需要用到的变量,这些变量不能通过Dagger直接注入,需要通过构造方法获得。
- 默认情况下组件创建Module的实例方法使用的是无参构造方法。
- 在执行注入动作时,需要通过重新设定组件的Module实例。
Dagger组件依赖与子组件
组件依赖与子组件主要解决了不同作用域时组件之间的复用问题:
- 在一个组件指定作用域后,就已经确定了该组件创建对象的生命周期。但是有些对象的实例可能生命周期更短,这个时候就需要定义新的组件。
- 新组件需要使用原组件的部分资源。
两种实现方式:
- 为@Component添加dependencies参数,指定该组件依赖于新的组件。(示例代码: https://gitee.com/sliverfoxwb/dagger-demo/tree/component-dependency/)
- 直接使用@SubComponent注解创建新的组件,并装载到父组件中。(示例代码: https://gitee.com/sliverfoxwb/dagger-demo/tree/subcomponent/)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 码行!
评论
ValineDisqus