为了便于理解,其实可以把component想象成针管,module是注射瓶,module里面的@Provides提供依赖对象是注入的药水,build方法是插进患者(Container),inject方法的调用是推动活塞。
Java Gradle
// Add plugin https://plugins.gradle.org/plugin/net.ltgt.apt
plugins {
id "net.ltgt.apt" version "0.5"
}
// Add Dagger dependencies
dependencies {
compile 'com.google.dagger:dagger:2.x'
apt 'com.google.dagger:dagger-compiler:2.x'
}
Android Gradle
// Add Dagger dependencies
dependencies {
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}
If you’re using classes in dagger.android you’ll also want to include:
额外添加
compile 'com.google.dagger:dagger-android:2.x'
compile 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
Tips
额,貌似变得更复杂了,还不如不用Dagger2呢。不过仔细想想也是可以理解的,直接组合方式虽然简单,但是具有耦合性,为了解决这种耦合,可能就会多产生一些辅助类,让这种直接的依赖关系,变为间接,降低耦合。跟大多数设计模式一样,为了达到高内聚低耦合,往往会有很多接口与类,Daager2也是如此,虽然看似复杂了些,不过这在软件工程中是值得的
依赖倒置原则
抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
抽象不应该依赖于具体,具体应该依赖于抽象。A. 高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
B. 抽象不应该依赖于具体实现,具体实现应该依赖于抽象。依赖注入是不在类中实例化其他依赖的类,而是先把依赖的类实例化了,然后以参数的方式传入构造函数中,
让上层模块和依赖进一步解耦。依赖注入的方式还有另外两种,一是构造器注入。二是setter
Dagger 2 极速入门 很简单的入门
Dagger2
1. 如果找不到被@Provides注释的方法提供对应参数对象的话,将会自动调用被@Inject注释的构造方法生成相应对象。
2. 区分@Provides 方法
3. 假设ActivityComponent依赖ApplicationComponent。当使用ActivityComponent注入Container时,如果找不到对应的依赖,就会到ApplicationComponent中查找。但是,ApplicationComponent必须显式把ActivityComponent找不到的依赖提供给ActivityComponent。
可能是东半球最好的dagger2文章 深度更深一些
@Qualifier不是直接注解在属性上的,而是用来自定义注解的。
神兵利器Dagger2 不错,没看完
通过registerActivityLifecycleCallbacks注入
存疑
@Component(modules = {SaladModule.class})//指明要在那些Module里寻找依赖
public interface SaladComponent {
//注意:下面这三个方法,返回值必须是从上面指定的依赖库SaladModule.class中取得的对象
//注意:而方法名不一致也行,但是方便阅读,建议一致,因为它主要是根据返回值类型来找依赖的
//★注意:下面这三个方法也可以不写,但是如果要写,就按照这个格式来
//但是当Component要被别的Component依赖时,
//这里就必须写这个方法,不写代表不向别的Component暴露此依赖
Pear providePear();
Banana provideBanana();
SaladSauce provideSaladSauce();
//注意:下面的这个方法,表示要将以上的三个依赖注入到某个类中
//这里我们把上面的三个依赖注入到Salad中
//因为我们要做沙拉
void inject(Salad salad);
}
思路整理
@Inject和@Module都可以提供依赖,那如果我们即在构造函数上通过标记@Inject提供依赖,有通过@Module提供依赖Dagger2会如何选择呢?具体规则如下:
- 步骤1:首先查找@Module标注的类中是否存在提供依赖的方法。
- 步骤2:若存在提供依赖的方法,查看该方法是否存在参数。
- a:若存在参数,则按从步骤1开始依次初始化每个参数;
- b:若不存在,则直接初始化该类实例,完成一次依赖注入。
步骤3:若不存在提供依赖的方法,则查找@Inject标注的构造函数,看构造函数是否存在参数。
- a:若存在参数,则从步骤1开始依次初始化每一个参数
b:若不存在,则直接初始化该类实例,完成一次依赖注入。
- Module并不是必需的,但Component是必不可少的;
- 编译后生成的Component实现类的名称是Dagger+我们所定义的Component接口的名称。
- Dagger2的依赖注入思想重在理解,希望小白们上手以后不单单是在使用它,更重要的是要理解它;Dagger2还有很多其他花式用法,比如在文里提到的一个Module两个方法返回值相同,还有懒加载等等,希望大家自己研究一下,以防不时之需。
在使用dagger2的过程中,在定义一些类或方法的名字的时候,要遵守一些谷歌提出的固定标准,以方便代码阅读与维护:
- 定义的Component和Module的名字是无所谓的,但是一般遵照以Component或Module结尾的名称;
- Module中用@Provides标注的方法的方法名是无所谓的,返回值是最重要的,但是一般遵照以provide开头的方法名;
- ==Component中返回值为void且有参的方法,方法名是无所谓的,参数是最重要的代表的是要注入的目标位置,但是方法名一般为inject;==
- ==Component中返回值不为void且无参的方法,方法名是无所谓的,返回值是最重要的代表的是暴露给子Component使用的依赖或者是获取的子Component的类型==。