Dagger2是一个Java和Android的依赖注入框架.
本文介绍Android中dagger2的基本使用.
其中包括@Inject, @Component, @Module和@Provides注解的使用.
使用依赖注入的好处
1.使用类和被依赖的对象构造分开,这样如果我们需要改变被依赖类的构造方法,不必改动每一个使用类.
2.对各种被依赖类的实例,可以只构造一次.
3.当我们需要更换一种实现时,只需要保证接口一致.
4.利于单元测试,我们可以方便地mock依赖类的对象.
优点总结: 创建对象和使用对象分离, 模块化增强.
注解说明:
@Inject: 通常在需要依赖的地方使用这个注解。换句话说,你用它告诉Dagger这个类或者字段需要依赖注入。这样,Dagger就会构造一个这个类的实例并满足他们的依赖。
@Module: Modules类里面的方法专门提供依赖,所以我们定义一个类,用@Module注解,这样Dagger在构造类的实例的时候,就知道从哪里去找到需要的 依赖。modules的一个重要特征是它们设计为分区并组合在一起(比如说,在我们的app中可以有多个组成在一起的modules)。
@Provide: 在modules中,我们定义的方法是用这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。
@Component: Components从根本上来说就是一个注入器,也可以说是@Inject和@Module的桥梁,它的主要作用就是连接这两个部分。 Components可以提供所有定义了的类型的实例,比如:我们必须用@Component注解一个接口然后列出所有的@Modules组成该组件,如 果缺失了任何一块都会在编译的时候报错。所有的组件都可以通过它的modules知道依赖的范围。
@Scope: Scopes可是非常的有用,Dagger2可以通过自定义注解限定注解作用域。后面会演示一个例子,这是一个非常强大的特点,因为就如前面说的一样,没 必要让每个对象都去了解如何管理他们的实例。在scope的例子中,我们用自定义的@PerActivity注解一个类,所以这个对象存活时间就和 activity的一样。简单来说就是我们可以定义所有范围的粒度(@PerFragment, @PerUser, 等等)。
Qualifier: 当类的类型不足以鉴别一个依赖的时候,我们就可以使用这个注解标示。例如:在Android中,我们会需要不同类型的context,所以我们就可以定义 qualifier注解“@ForApplication”和“@ForActivity”,这样当注入一个context的时候,我们就可以告诉 Dagger我们想要哪种类型的context。
Dagger2 具体使用案例:
1.配置
在AppMode 下的build.gradle进行配置,然后同步就可以导入相关dagger2的包:
/***************************************使用dagger2需要的配置Start*****************************************/
apply plugin: 'com.neenbedankt.android-apt'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
/************使用dagger2需要的配置End************************/
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
/************dagger2使用需要的库start***********************/
compile "com.google.dagger:dagger:2.9"
apt 'com.google.dagger:dagger-compiler:2.9'
//Dagger2中会用到@Generated注解,而AndroidSDK中没有javax.anotation.Generated.class,所以在 Android 项目要添加此句
provided 'org.glassfish:javax.annotation:10.0-b28'
/***********dagger2使用需要的库end*************************/
}
2.创建一个类Student用于测试Mode
/**
* Created by lixby on 2017/8/10.
*/
public class Student {
private String sName;
private String sSex;
private String sAge;
public Student(String sName, String sSex, String sAge) {
this.sName = sName;
this.sSex = sSex;
this.sAge = sAge;
}
public String getsAge() {
return sAge;
}
public void setsAge(String sAge) {
this.sAge = sAge;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
public String getsSex() {
return sSex;
}
public void setsSex(String sSex) {
this.sSex = sSex;
}
public void showStudentInfo(){
Log.i("lixby","student Name:"+sName);
Log.i("lixby","student sSex:"+sSex);
Log.i("lixby","student sAge:"+sAge);
}
}
3.创建StudentModule,用于体提供Student实例给其他地方使用,代码很简单,一定要注意提供@Module 和@Provides 注解,要不无法没被Dagger2识别:
/**
* Created by lixby on 2017/8/10.
*/
@Module
public class StudentModule {
@Provides
public Student provideStudent(){
return new Student("小明","男","18");
}
}
4.创建AppComPonent
/**
* Created by lixby on 2017/8/10.
*/
@Singleton
@Component(modules = {ApplicationModule.class,StudentModule.class})
public interface AppComPonent {
//MainActivity 目标类
void inject(MainActivity mainActivity);
}
Component是注入器,它一端连接目标类,另一端连接目标类依赖实例,它把目标类依赖实例注入到目标类中。上面的Module是一个提供类实例的类,所以Module应该是属于Component的实例端的(连接各种目标类依赖实例的端),Component的新职责就是管理好Module,Component中的modules属性可以把Module加入Component,modules可以加入多个Module。
第三和第四中,Module中的创建类实例方法用Provides进行标注,Component在搜索到目标类中用Inject注解标注的属性后,Component就会去Module中去查找用Provides标注的对应的创建类实例方法。
5.按照上面步骤完成Module和Component的创建,然后执行Rebuild Project就会自动生成对应的关联文件。
6.初始化AppComPonent
/**
* Created by lixby on 2017/8/10.
*/
public class MyApplication extends Application{
static AppComPonent mAppComPonent;
@Override
public void onCreate() {
super.onCreate();
inItDaggerModule();
}
private void inItDaggerModule(){
mAppComPonent= DaggerAppComPonent.builder()
.applicationModule(new ApplicationModule(this))
.studentModule(new StudentModule())
.build();
}
public static AppComPonent getComponent() {
return mAppComPonent;
}
}
7.在MainActivity中通过@Inject 将Student注入,就可以使用Student 实例了:
public class MainActivity extends AppCompatActivity {
@Inject
Student mStudent;
@Override
protected void onCreate(Bundle savedInstanceState) {
MyApplication.getComponent().inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStudent.showStudentInfo();
}
}
总结:
Inject,Component,Module,Provides是dagger2中的最基础最核心的知识点。奠定了dagger2的整个依赖注入框架。
Inject主要是用来标注目标类的依赖和依赖的构造函数
Component它是一个桥梁,一端是目标类,另一端是目标类所依赖类的实例,它也是注入器(Injector)负责把目标类所依赖类的实例注入到目标类中,同时它也管理Module。
Module和Provides是为解决第三方类库而生的,Module是一个简单工厂模式,Module可以包含创建类实例的方法,这些方法用Provides来标注
这个Demo很简单,只是初识,还需要进一步在实践中去使用和总结。