Dagger2初探
背景
A类持有B类的引用,如果B类的构造函数发生改变,则A类也需要修改;不仅仅是A类,但凡持有B类引用的地方都需要修改。这个就是 Dagger2 解决的问题。
Dagger2
引入
- 在 build.gradle (Project) 添加 apt 插件
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
- 在 build.gradle 中添加依赖
apply plugin: 'com.android.application'
//应用apt插件
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
...
// 添加如下引用
provided 'org.glassfish:javax.annotation:10.0-b28'
compile 'com.google.dagger:dagger:2.5'
compile 'com.google.dagger:dagger-compiler:2.5'
}
使用
DaggerActivity,需要有一个 **DaggerPresenter **的成员
第一步:创建Module
- 创建Module——**Module **的作用是用来提供生成依赖对象的,现在需要注入DaggerPresenter 对象,那么Module的作用就是生成一个DaggerPresenter 对象
- 该类需要用 @Module 注解
- 既然需要提供一个DaggerPresenter 对象,那么第一步就应该提供生成DaggerPresenter 对象的方法
- DaggerPresenter 的构造函数需要DaggerActivity 和User对象,所以第二步需要生成DaggerActivity 和User对象
@Module
public class ActivityModule {
private DaggerActivity activity;
public ActivityModule(DaggerActivity activity) {
this.activity = activity;
}
//第二步
@Provides
public DaggerActivity provideActivity() {
return activity;
}
//第二步
@Provides
public User provideUser(){
return new User("user created in ActivityModule");
}
//第一步
@Provides
public DaggerPresenter providePresenter(DaggerActivity activity, User user) {
return new DaggerPresenter(activity,user);
}
}
第二步:创建Component
@Component(modules = ActivityModule.class)
public interface ActivityComponent {
void inject1(DaggerActivity activity);
}
-
Component
需要用@Component
注解来标识 - 同时声明
module
- 提供了一个
inject1
方法,方法名随意,参数不能改
第三步:Make Project
完成之后 **apt **会自动生成一个 以 Dagger 开头的 Component,比如,我们上面写的是 **ActivityComponent **,生成了类名就为 DaggerActivityComponent。这个类我们可以直接使用
第四步:注入Activity
在 **Activity **的 **onCreated **函数中编写如下代码
@Inject
MvpPresenter presenter;
DaggerActivityComponent.builder()
.activityModule(new ActivityModule(this))
.build()
.inject1(this);
首先调用这个了类的 builder(),然后调用 module,调用build,调用Component的inject1方法
这里通过 new MainModule(this) 将 view 传递到 MainModule 里,然后 MainModule 里的 provideMainView() 方法返回这个 View,当去实例化 MainPresenter 时,发现构造函数有个参数,此时会在 Module 里查找提供这个依赖的方法,将该 View 传递进去,这样就完成了 presenter 里 View 的注入
解释说明
在MVP模式中,最常见的一种依赖关系,就是 Activity 持有 presenter 的引用,并在 Activity 中实例化这个 presenter,即 Activity 依赖 presenter,presenter 又需要依赖 View 接口,从而更新 UI
使用Dagger2的话代码如上使用Dagger,
先看 Activity,之前是直接声明 MvpPresenter
,现在是在声明的基础上加了一个注解@Inject
,表明 MainPresenter 是需要注入到 Activity 中的,使用 @Inject 时,不能用 private 修饰符修饰类的成员属性
然后我们在 MainPresenter 的构造函数上同样加了 @Inject 注解。这样 MainActivity 里的 mainPresenter 与他的构造函数建立了某种联系。这种联系我们可以这样理解,当看到某个类被 @Inject 标记时,就会到他的构造方法中,如果这个构造方法也被 @Inject 标记的话,就会自动初始化这个类,从而完成依赖注入。
这种联系不会凭空建立 ,需要一个桥梁就是我们创建的Component,Component 是一个接口或者抽象类,用 @Component 注解标注
-
@Inject
带有此注解的属性或构造方法将参与到依赖注入中,Dagger2 会实例化有此注解的类 -
@Module
带有此注解的类,用来提供依赖,里面定义一些用@Provides
注解的以 provide 开头的方法,这些方法就是所提供的依赖,Dagger2 会在该类中寻找实例化某个类所需要的依赖。 -
@Component
用来将@Inject
和@Module
联系起来的桥梁,从@Module
中获取依赖并将依赖注入给@Inject
注意
- Component可以依赖别的Component,比如 下面这个依赖的是 NetComponent
@UserScope
@Component (modules = SplashModule.class,dependencies = NetComponent.class)
public interface SplashComponent {
void inject(SplashActivity splashActivity);
}
参考