什么是dagger2
Dagger2是Dagger的升级版,是一个依赖注入框架,现在由Google接手维护。 恩,这里有个关键字依赖注入,因此我们得先知道什么是依赖注入,才能更好的理解Dagger2。
依赖注入是面向对象编程的一种设计模式,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。
什么是依赖注入?当 A 类中包含一个属性 B 类,就可以说 A 对 B 产生了 依赖。当实例化一个对象的时候,不再需要 new 出一个实例,而是由框架自动的帮你生成一个实例,这就是 注入。
简单的说,就是程序运行之前需要某些基础数据,这些基础数据就叫做依赖的数据。
依赖注入有以下几种方式:
-
通过接口注入
interface ClassBInterface {
void setB(ClassB b);
}public class ClassA implements ClassBInterface { ClassB classB; @override void setB(ClassB b) { classB = b; } }
-
通过set方法注入
public class ClassA {
ClassB classB;public void setClassB(ClassB b) { classB = b; } }
-
通过构造方法注入
public class ClassA {
ClassB classB;public void ClassA(ClassB b) { classB = b; }
-
通过Java注解
public class ClassA {
//此时并不会完成注入,还需要依赖注入框架的支持,如RoboGuice,Dagger2
@inject ClassB classB;... public ClassA() {}
在Dagger2中用的就是最后一种注入方式,通过注解的方式,将依赖注入到宿主类中。
在 Android Studio 中配置 Dagger2
Dagger2 是一个通用的 java 库,并不只适用于 Android,这里仅以 Studio 下的 Android 开发示例。
在项目的根 build.gradle 里添加:
buildscript {
...
dependencies {
...
//编译时处理注解的插件,生成代码就靠它
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
在module的build.gradle添加:
apply plugin: 'com.neenbedankt.android-apt'
android{
...
}
dependencies {
provided 'org.glassfish:javax.annotation:10.0-b28'
compile 'com.google.dagger:dagger:2.5'
compile 'com.google.dagger:dagger-compiler:2.5'
}
贴上整个gradle:
apply plugin: 'com.android.application'
//dagger add
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.example.ibesteeth.gjj_dagger_demo"
minSdkVersion 17
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha1'
testCompile 'junit:junit:4.12'
//dagger2
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
//java注解
compile 'org.glassfish:javax.annotation:10.0-b28'
//Square
compile 'com.jakewharton:butterknife:6.1.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.3.0'
}
Dagger2 中的注解
@Module
注解一个类,这个类用来提供依赖,或者通俗的说,完成各种对象的实例化 的一个集合。类里面可以包含很多@Provides
注解的方法,每个方法对应一种对象的创建。
@Provides
注解 Module 类里面的方法,Dagger 会在需要创建实例的时候找到这个方法并调用,完成对象的实例化。
这样说可能还是太抽象,看一个实例:
//apiservice的工厂类
@Module
public class ApiServiceModule {
@Provides
int getId(){
return 0;
}
@Provides
String getName(){
return "testName";
}
@Provides
@Singleton
ApiService provideApiServiceNull(int id,String name) {
return new ApiService(id,name);
}
}
@Module 注解的含义很简单,它就是告诉 Dagger 框架,这个类里面有可以提供对象创建的方法。所以 Module 类可以理解成一个用来组织对象创建方法的容器,关键是其内部的方法。
我的理解其实就是,生成bean对象的一个辅助类,相当于factory工厂类
注意:任何 Module 类的开头都以 @Module 进行注解。
@Inject
当注解一个属性的时候,表示该属性需要依赖(需要被注入一个对象)。
当注解一个构造函数的时候,表示该构造函数可以提供依赖。需要注意的是,如果被 @Inject 注解的构造函数是带参数的,比如这样:
@Component
前面说了 @Module 提供依赖, @Inject请求依赖,而@Component 就是联系这两者的纽带。
Component 主要说明4件事:
谁来提供依赖
该 Component 依赖哪些其他的 Component
该 Component 为谁提供依赖注入
该 Component 可以提供那些依赖
@Component 注解的是一个接口,比如下面这个接口,表示它可以提供一个 MyApplication 类型的依赖。
对应前面说的4点:
- module
参数{}里的类就表示提供依赖的Module类(可以有多个),也就是用@Module
注解的类 - dependencies
表示该 Component 提供的注入类的构造函数中,还依赖其他@Component
提供的一些类。 - 有参无反的方法指明该 Component 注入的目标,比如本例中,就说明 MyActivity 中需要 AppComponent 提供的依赖
- 有反无参的方法指明该 Component 可以提供哪些依赖,或者说暴露哪些依赖。因为这里可能会有疑问,Component 可提供的依赖不就是 Module 里的那些吗?确实没错,但是 Component 也可以有选择的只对外界暴露它的一部分能力,并不一定会声明所有的在 Module 里定义的类。
这个接口可以理解成一份声明,告诉Dagger哪些对象可以被注入,以及谁(Module类中被@Provides
注解的方法)来提供这些依赖。需要注意,只有在 Component 接口中声明了的类,才会被暴露给依赖它的其他 Component。也就是说,Module 类中提供的依赖,并不一定都会在 Component 中声明。
最后,这个接口的实现会由 Dagger 框架自动生成,生成类的名字满足 *Dagger + 你的接口名
的格式。可以在 项目的app-buile
目录下找到生成的代码。后面的使用也主要是跟 Component 的实现类打交道。
我们来重新理一遍上面的注入过程,首先弄清楚以下几个概念:
@Inject 带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类
@Module 带有此注解的类,用来提供依赖,里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所需要的依赖。
@Component 用来将@Inject和@Module联系起来的桥梁,从@Module中获取依赖并将依赖注入给@Inject
Component--工厂管理员
注意
当module中创建对象的时候,需要传入参数的时候,需要添加传入参数的获取
参考ApiServiceModule类里面的代码