侧边栏壁纸
博主头像
慢行的骑兵博主等级

贪多嚼不烂,欲速则不达

  • 累计撰写 29 篇文章
  • 累计创建 27 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Dagger2基本用法和源码分析

慢行的骑兵
2021-09-29 / 0 评论 / 0 点赞 / 124 阅读 / 1,878 字
  • 该篇笔记主要是对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生成的文件

01.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当做工具,要善于使用该工具,让其有利于项目的开发,把握好使用尺度是个难点,得不断地练习;
0

评论区