Dagger2简介
Dagger2是Dagger的升级版,是一个依赖注入框架,第一代由大名鼎鼎的Square公司共享出来,第二代则是由谷歌接手后推出的,现在由Google接手维护。
Githu:https://github.com/google/dagger
依赖注入
依赖注入是面向对象编程的一种设计原则,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。
举个栗子:
public class ClassA {
private ClassB b
public ClassA(ClassB b) {
this.b = b;
}
}
这里ClassA的构造函数里传了一个参数ClassB,随着后续业务增加也许又需要传入ClassC、ClassD。试想一下如果一个工程中有5个文件使用了ClassA那是不是要改5个文件?
这既不符合开闭原则,也不符合单一职责原则,这个时候大杀器Dagger2就该出场了:
public class ClassA {
@inject
private ClassB b;
public ClassA() {
}
}
通过注解的方式将ClassB b注入到ClassA中,可以灵活配置ClassA的属性而不影响其他文件对ClassA的使用。
简单的说,就是一个工厂模式,由Dagger负责创建工厂,帮忙生产instance。遵从Java规范JSR 330,可以使用这些注解。现在不研究Dagger2是如何根据注解去生成工厂的,理解为什么可以实现DI(Dependency Injection),如何创建IoC(Inverse of Control)容器。

Dagger2使用
在实际项目中Dagger2一般和MVP模式配合使用
引入Dagger2
api 'com.google.dagger:dagger:2.28.3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.28.3'
定义IView
//IView类
public interface ICommonView {
Context getContext();
}
定义Module
创建一个类CommonModule
@Module
public class CommonModule {
private ICommonView iView;
public CommonModule(ICommonView iView) {
this.iView = iView;
}
@Provides
public ICommonView provideIcommonView() {
return this.iView;
}
}
定义Component
创建一个接口CommonComponent
@Component (modules = CommonModule.class)
public interface CommonComponent {
void inject(LoginActivity activity);
}
定义Presenter
build一下项目,然后在LoginPresenter里使用@Inject(@Inject来自javax包,不是Dagger2自定义的)
public class LoginPresenter {
ICommonView iView;
@Inject
public LoginPresenter(ICommonView iView) {
this.iView = iView;
}
public void login(User user) {
Context mContext = iView.getContext();
Toast.makeText(mContext, "login......", Toast.LENGTH_SHORT).show();
}
}
使用CommonComponent接口
在LoginActivity中使用CommonComponent接口
public class LoginActivity extends AppCompatActivity implements ICommonView {
@BindView(R.id.btn_login)
Button btn;
@Inject
LoginPresenter presenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
DaggerCommonCompnent
.builder()
.commonModule(new CommonModule(this))
.build()
.inject(this);
}
@OnClick(R.id.btn_login)
void login() {
presenter.login(new User());
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public Context getContext() {
return this;
}
}
解耦
有没有注意到loginPresenter并没有初始化?这个简单Demo要展示的重点就是loginPresenter和LoinActivity彻底解藕,后续无论怎样修改loginPresenter的构造方法都不需要改动LoinActivity的代码。如果loginPresenter构造函数增加参数要改谁的代码呢?当然是CommonModudle了,其实也很简单,例如增加了一个新参数ImyView就在CommonModudle.java中新增一个方法
@Provides
public ImyView provideMyView() {
return myView; // myView是ImyView的实例
}
注意别漏了@Provides,它是Dagger2自定义的注解,也是通过它Dagger2才能正常把新增的参数传入loginPresenter构造器。
命名规约
@Provides方法用provide前缀命名@Module用Module后缀命名@Component以Component作为后缀
Dagger2总结
Dagger2是通过依赖注入完成类的初始化,这个过程需要三部分:
- 依赖提供方(生产者)
- 依赖注入容器(桥梁)
- 依赖需求方(消费者)
Dagger2是怎么选择依赖提供的呢,规则是这样的:
步骤1:查找Module中是否存在创建该类的方法
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束




