在 Gradle 中的使用
1 | implementation 'com.google.dagger:dagger:2.4' |
基本使用
1 | public class MainPresenter implements IPresenter { |
1 | // Module |
1 | // 注入器, 被注入的对象(MainPresenter)和注入的类(MainActivity)的桥梁 |
1 | public class MainActivity extends AppCompatActivity implements IView{ |
生成类流程图
简单总结:
@Inject 带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类
@Module 带有此注解的类,用来提供依赖,里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所需要的依赖。
@Component 用来将@Inject和@Module联系起来的桥梁,从@Module中获取依赖并将依赖注入给@Inject
不同注解的含义
@Inject
@Inject用于注解构造函数或成员变量
作用于成员变量时
Dagger2根据该注解及成员变量的类型,从moudle中得到相应实例。
注意:成员变量的访问修饰符不能是private
作用于构造函数时
就是Dagger2对于获取对象实例的方式2,比如上面的例子其实可以直接在Presenter的构造函数上注解@Inject,并移除@Provides注解的方法
@Inject 不适用的情况
- 不具有构造函数的接口
- 远程引入的三方库中的类无法被添加注解
- 通过建造者模式等方式可配置化的进行构造的对象
(使用@Provides可以处理这些问题)
@Module
@Module注解用于获取对象实例的类,Dagger2根据该注解知道应该去哪个类里获取对象实例 (上面的方式 1)
@Provides
@Provides注解用于module类中获取对象实例的方法,Dagger2根据该注解及方法的返回值类型将对象实例注入到对应的引用中
@Component
@Component注解用于担任连接桥梁的接口,其两端分别是在@Component的参数中指定的modules数组和在方法参数中指定的具体类
注意:方法参数必须是要注入的具体类,而非其父类或接口
注:
方式一的优先级高于方式二:
在供应某实例时,会先通过方式一查找是否存在返回该实例的的方法
如果存在,则获取实例并对外供应
如果不存在,再通过方式二查找是否存在@Inject标注的构造函数
如果存在,则将通过该构造函数构造实例并对外供应
如果不存在,那将报错,因为无法供应所需的实例
@Singleton
使得对象成为单例只需要同时在@Provides注解的方法和component接口上添加@Singleton这个注解即可。
1 |
|
方式 1:
1 |
|
或者方式 2:
1 |
|
源码:
1 |
|
注意: @Singleton 并不代表单例, 真正起作用的事 @Scope 这个注解.
可以使用任意的被 @Scope 所注解的注解,来替代 @Singleton ,都可以实现单例.
@Scope 是通过 DoubleCheck 缓存获取到的对象实例实现 Component 的组件的生命周期内的对象的单例性.
@Binds
当注入抽象类时使用 @Binds
1 | public abstract class Factory {} |
1 |
|
注:
- @Binds注解用于module中的抽象方法,这个方法的参数应该是具体实现类,返回值应该是抽象类,它高速Dagger2在自动生成的代码中注入抽象类引用对象时,应该使用哪一个具体实现类作为实例被获取
- 在使用抽象类作为module时,获取实例对象的方法只能使用static静态方法
@Named
1 |
|
以上代码, 返回多个同一类的实例时, Dagger2 无法仅仅通过返回类型来判断是调用哪个方法创建实例时,就需要使用 @Named 了
1 |
|
使用时:1
2
3
"factoryA") (
Factory factory;
dependencies
将App中的单例对象同样注入到MainActivity中, 需使用 dependencies
1 |
|
- 这里依赖之后会产生一个小问题,就是存在依赖关系的组件的作用域标记不能相同,因为在AppComponent中我们标记了@Singleton,因此在这里我们自定义了新的@Scope,即@ActivityScope
1 |
|
- 并且,在构建 MainComponent 实例时,需要传进 AppComponent 实例
1 | public class MainActivity extends AppCompatActivity { |
- 最后,我们需要给AppComponent接口添加一个方法,用来提供其所持有的单例对象
1 |
|
Lazy
懒加载机制, 需要它在真正被使用时才被实例化,那么你可以使用Lazy,这里以Product为例,代码修改如下即可
1 |
|