Dagger2是什么?
Dagger2是Dagger的升级版,是一个依赖注入框架,第一代由大名鼎鼎的Square公司共享出来,第二代则是由谷歌接手后推出的,现在由Google接手维护.
Github地址
那么,什么是依赖注入?
依赖注入是面向对象编程的一种设计原则,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的.
举个栗子:
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的使用.
如何使用Dagger2
在实际项目中Dagger2一般和MVP模式配合使用。下面我们先写个简单的Demo体验一下Dagger2.
1.新建一个Demo,模拟登录业务.Model,View,Presenter很简单:
model :
//model 类
public class User implements Serializable
{
private int id;
private String userName;
private String pwd;
}
//IView类
public interface ICommonView
{
Context getContext();
}
View :
//activity
public class LoginActivity extends AppCompatActivity implements ICommonView
{
@BindView(R.id.btn_login)
Button btn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
}
@OnClick(R.id.btn_login) void login(){
}
@Override
public Context getContext() {
return this;
}
}
presenter:
public class LoginPresenter
{
ICommonView iView;
public LoginPresenter(ICommonView iView){
this.iView = iView;
}
public void login(User user){
Context mContext = iView.getContext();
Toast.makeText(mContext,"login......",Toast.LENGTH_SHORT).show();
}
}
Demo的页面长这样 :
2.导入Dagger2
compile"com.google.dagger:dagger:2.14.1"
annotationProcessor"com.google.dagger:dagger-compiler:2.14.1"
咦?一般的第三方库像Glide,okhttp不都是一行代码引入吗?这里怎么多了一个annotationProcessor?估计用过其他注解框架比如Butterknife,EventBus的同学已经了然了,小白也不要急,后面会讲,先体验一把再说.
2.定义一个注解ActivityScope
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
这个注解ActivityScope是干啥的?怎么里面啥内容都没有?别急,先放着。
3.创建一个类CommonModule,注意这里用到了刚才定义的@ActivityScope注解
@Module
public class CommonModule{
private ICommonView iView;
public CommonModule(ICommonView iView){
this.iView = iView;
}
@Provides
@ActivityScope
public ICommonView provideIcommonView(){
return this.iView;
}
}
4.创建一个接口CommonComponent,
@ActivityScope
@Component (modules = CommonModule.class)
public interface CommonComponent {
void inject(LoginActivity activity);
}
5.build一下项目,然后在LoginPresenter里使用@Inject
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();
}
}
6.在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并没有初始化?这里一个重点就是loginPresenter和LoinActivity 解藕了,后续无论怎样修改loginPresenter的构造方法都不需要改动LoinActivity的代码。那要改谁的代码呢?当然是CommonModudle了。
先解释一下上面的几个问题,
annotationProcessor"com.google.dagger:dagger-compiler:2.14.1"是什么情况?
annotationProcessor是处理注解的工具,是APT(Annotation Processing Tool)
的一种,简单来说注解提供的都是一种“标记”,真正使这些“标记”work的是APT,在build的过程中,APT(就是dagger-compiler)扫描到注解(@Component@Module)生成的.这个过程用下面这张图表示:
那么apt扫描之后会怎样呢?看一下上面demo的build-->generate-->source-->apt目录下面都有什么:
生成了很多文件。就是apt替我们写了很多类和实现方法。这些文件里面的内容墙裂推荐大家看看。
ActivityScope是干啥的?怎么里面啥内容都没有?
自定义注解ActivityScope作用是限定被它标记的对象生命周期与对应的Activity相同(笑)。其实注解里我们使用了2个元注解
@Scope:标记局部单例;@Retention :指定了它是运行时注解,就是说注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在.
那么,就凭这两个元注解,为啥可以限定被它标记的对象生命周期与对应的Activity相同呢?我们看一下CommonComponent生成类
瞅见哪个DoubleCheck了吗?就是说这里是提供了一个provideIcommonViewProvider单例;那这个provideIcommonViewProvider是干啥的呢?再看看这张截图,
看看LoginPresenter的构造方法就知道provideIcommonViewProvider的作用了。那为啥说提供了provideIcommonViewProvider单例就保证了生命周期和LoginActivity绑定了呢?如果还不明白就想想LoginPresenter的生命周期。
好了,写到这里Dagger2的用法和原理算是“浅出”了,下一篇文章再进行“深入”。
抱歉之前没看明白的各位老铁,文章更新了,尽量写的简介,希望对你们有帮助。
Demo github地址
参考博客:
Dagger2:
https://www.jianshu.com/p/22c397354997
https://www.jianshu.com/p/39d1df6c877d
APT:
https://www.jianshu.com/p/1910762593be
https://blog.csdn.net/Ru_Zhan/article/details/78232851?locationNum=8&fps=1