- 该篇笔记主要是对Dagger的使用做一个总结,并对其源码进行分析。
一.IOC
- 简单描述:IOC(Inversion of Control)是原来由程序代码中主动获取的资源,转变由第三方获取并使原来的代码被动接收的方式,以达到解耦的效果,称为控制反转;
- 目标:解耦;
二.认识Dagger2
1.使用原因
- 国外排行前1w的app有74%都使用了Dagger2
2.基本配置
implementation 'com.google.dagger:dagger:2.4'
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'
3.使用逻辑
3.1.module
- 用来提供对象
3.2.component
- 用于组织module并进行注入
3.3.使用提供的对象
- 如在Activity中需要使用module提供的javabean对象,则需要使用@Inject注解,并按照Dagger2的规范来操作,具体的使用,请看下一节;
4.认识基本使用
-
Dagger2涉及了不少的规范,一开始直接切入规范,会比较晕。
-
我们先按照一条路线,实现Ioc的效果,然后分析这条路线上的点,接着再来分析Dagger2使用相关的其它内容;
-
在3中,我们提及到了4个目标,javabean,module,component和使用javabean的地方,javabean很好理解,使用javabean的对方我们先定为activity,然后,我们看一下module和component,上一下代码。
//1.javabean
public class Person {
//先啥也不写,从简单的入手
}
//2.module
//名字随便取,是个class
//注意:有注解@Module和@Provides,还有一个方法,方法的名字也是随便定义的
@Module
public class BeanModule {
@Provides
public Person providePerson(){
return new Person();
}
}
//3.component
//是个interface
//名字随便取
//使用到了注解,并关联了BeanModule
//同时还定义了一个方法(方法名随便取),参数有讲究,刚刚提到过使用javabean的对方我们先定为activity,这里我们是在MainActivity中使用,故参数传递的是MainActivity
@Component(modules = {BeanModule.class})
public interface BeanComponent {
//注入 注意:这里不能使用多态
void injectMainActivity(MainActivity mainActivity);
}
- 我们现在看到3中的四个对象大概的外貌,准备工作算是完成了,下面就是真正的使用(在MainActivity中),不过我们得rebuild(这是规范中的一步) 一下项目,让APT生成需要的文件,以便帮我们生成代码来实现我们想要的效果;
public class MainActivity extends AppCompatActivity {
//第二步
@Inject
Person mPerson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//第一步
//DaggerBeanComponent.create().injectMainActivity(this);
//或者
DaggerBeanComponent
.builder()
.beanModule(new BeanModule())
.build()
.injectMainActivity(this);
System.out.println("mPerson " + (mPerson == null));
}
}
- 现在呢,我们就可以在MainActivity中使用Person对象了;
- 关于在MainActivity中使用Person对象,我们绕了很大一个弯子,不用Dagger2多简单,一个new关键字就搞定了。但是,我们再创建复杂对象的时候,Dagger2魅力太大了,我们相当于通过BeanModule对Person做了一层封装,后续Javabean的一些修改,直接在BeanModule中操作即可。
- 关于Dagger2,是一把双刃剑,用的好非常nice,用得不好非常难受,什么时候用,用到什么程度得实践之后才有一个很好的掌控;
- 现在简单总结一下:关于Dagger2,实际上也是用来提供对象的,只不过其使用起来有很多规范,也就是我们需要学习的东西了,其入门和理解都不是容易的事情,自己在学习的过程中走了很多弯路。但是,不能畏惧,循序渐进的学是最轻松、最快的。到此,我们虽然还不知道具体怎么用,但只要有了一个抽象的认识,那就够了。
- 推荐的学习方案:我们先从源码(不要自己摸索,通过资料或者视频来学习)这块学习,看其源码的实现方式,接着再看其用法,那就很容易了。
三.源码分析
- 按照Dagger2的规范写代码之后,会通过APT生成相关代码,源码分析会进入这些生成的代码中;
1.APT生成的文件
2.分析DaggerBeanComponent.xxx
- 分析下方的源码
//源码的分析入口
DaggerBeanComponent
.builder()
.beanModule(new BeanModule())
.build()
.injectMainActivity(this);
3.查看DaggerBeanComponent类
public final class DaggerBeanComponent implements BeanComponent {
private Provider<Person> providePersonProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerBeanComponent(Builder builder) {
assert builder != null;
//4.调用initialize方法
initialize(builder);
}
public static Builder builder() {
//1.new Builder对象,在2中分析
return new Builder();
}
public static BeanComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
//6.调用BeanModule_ProvidePersonFactory的方法
this.providePersonProvider = BeanModule_ProvidePersonFactory.create(builder.beanModule);
//7.调用MainActivity_MembersInjector的方法
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(providePersonProvider);
}
//8.调用了mainActivityMembersInjector的方法
@Override
public void injectMainActivity(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity);
}
//1.调用builder()静态方法
public static final class Builder {
private BeanModule beanModule;
private Builder() {}
//3.创建了DaggerBeanComponent对象,如果beanModule未被赋值,默认new一个BeanModule
public BeanComponent build() {
if (beanModule == null) {
this.beanModule = new BeanModule();
}
return new DaggerBeanComponent(this);
}
//2.给Builder中的beanModule赋值
public Builder beanModule(BeanModule beanModule) {
this.beanModule = Preconditions.checkNotNull(beanModule);
return this;
}
}
}
4.调用BeanModule_ProvidePersonFactory的方法
public final class BeanModule_ProvidePersonFactory implements Factory<Person> {
private final BeanModule module;
public BeanModule_ProvidePersonFactory(BeanModule module) {
assert module != null;
this.module = module;
}
//提供了get方法,获得定义javabean对象
@Override
public Person get() {
return Preconditions.checkNotNull(
module.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<Person> create(BeanModule module) {
//6.1.创建BeanModule_ProvidePersonFactory对象,将module赋值为传递过来的BeanModule
return new BeanModule_ProvidePersonFactory(module);
}
}
5.调用MainActivity_MembersInjector的方法
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<Person> mPersonProvider;
public MainActivity_MembersInjector(Provider<Person> mPersonProvider) {
assert mPersonProvider != null;
this.mPersonProvider = mPersonProvider;
}
public static MembersInjector<MainActivity> create(Provider<Person> mPersonProvider) {
//7.1.调用 MainActivity_MembersInjector的构造方法,将创建的好的mPersonProvider对象传递进取
return new MainActivity_MembersInjector(mPersonProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
//8.1.给MainActivity的mPerson进行赋值
//mPersonProvider在7.1中已经被赋值
//mPersonProvider.get()方法调用 ---> BeanModule_ProvidePersonFactory的get ---> BeanModule的providePerson方法。即:MainActivity的mPerson = new Person()
instance.mPerson = mPersonProvider.get();
}
public static void injectMPerson(MainActivity instance, Provider<Person> mPersonProvider) {
instance.mPerson = mPersonProvider.get();
}
}
6.分析mainActivityMembersInjector的injectMembers方法
public interface MembersInjector<T> {
void injectMembers(T instance);
}
//找其实现类MainActivity_MembersInjector,回到5中的injectMPerson方法,继续分析
7.总结
- 到此,Dagger2的源码已经分析完毕。底层就是最原始的东西。
四.Dagger2的用法的注意点
- 这个时候,我们再去搜索博客进行学习相对就比较容易了,但是,还是得从简单,常用的用法入手,进而再学习复杂的用法;
- 在实际的业务开发中,跟Dagger2相关的需要考虑的有,单例,全局的单例,多个component组合依赖,带参数module,@Named的使用,lazy 和 Provider的使用。在提到的这几点上加以训练,Dagger2的使用基本上足够了。
- 一定要记住,把Dagger2当做工具,要善于使用该工具,让其有利于项目的开发,把握好使用尺度是个难点,得不断地练习;
评论区