天天看点

Dagger2的使用以及源码分析

一,简介

Dagger2是Dagger1的分支,由谷歌公司接手开发的,Dagger2中没有再使用反射机制,而是使用派遣方法,自动生成如同自己手写的代码,好处是:第一,谷歌声称提高了13%的效率;第二,代码的调试变得更简单,缺点是缺乏灵活性。

二,接入

在项目的gradle文件中添加

dependencies {
        classpath 'com.android.tools.build:gradle:2.2.2'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
    }
           

在app的gradle文件中添加插件

apply plugin: 'com.neenbedankt.android-apt'
           

添加依赖

apt 'com.google.dagger:dagger-compiler:2.0'
compile 'com.google.dagger:dagger:2.0'
           

三,使用

首先了解一下dagger2中的几个注解:

@Inject,该注解有两个作用,标记变量,表示改变量有Dagger2容器提供,不需要自己初始化;标记构造函数,表示该类可以由Dagger2在需要的时候找到该构造方法,并提供该类的实例。

@module,标注用于提供需要注入的实例的类,当我们要提供第三方的依赖时,使用Inject注解类的构造函数很明显不现实,这时就可以使用这个注解,在module中提供。

@Provides,使用在用@module标注的类里面,告诉dagger2来这里找依赖。

@Component,用于标注接口,用来连接依赖提供者和依赖需求者。

@Qulifier,用于自定义注解,主要作用是当我们提供多个类型相同的依赖,可以用该注解区分。

@Scope,用于自定义注解,主要用于实现单例。

@Singleton,该注解就是通过@scope定义的注解,一般用于提供全局单例。

事件出真知,我们以汽车和引擎为例

案例1

引擎类,依赖提供

public class Engine {

    @Inject
    public Engine() {
    }

    public void start(){
       System.out.print("引擎发动了");
    }
}
           

汽车类,依赖需求

public class Bus {
    @Inject
    Engine engine;

    public Bus(){
        DaggerBusComponent.builder().build().inject(this);
    }
}
           

@component标注类,相当于注入器,把Engine对象注入到Bus对象中,注意在该类写好后需要rebuild一下,否则不会生成上面的DaggerBusComponent类

@Component
public interface BusComponent {
    void inject(Bus bus);
}
           

测试类,测试

public class TestMain {

    public static void main(String args[]) {
        new Bus().engine.start();
    }
}
           

运行之后,如愿打印出信息,那我们就来分析一下,这个简单的例子是怎么实现依赖注入的呢?

四,源码分析

这里一共涉及到三个类,DaggerBusComponent,Bus_MembersInjector,Engine_Factory

public final class DaggerBusComponent implements BusComponent {
    private MembersInjector<Bus> busMembersInjector;

    private DaggerBusComponent(Builder builder) {
        assert builder != null;
        initialize(builder);
    }

    public static Builder builder() {
        return new Builder();
    }

    public static BusComponent create() {
        return builder().build();
    }

    @SuppressWarnings("unchecked")
    private void initialize(final Builder builder) {

        this.busMembersInjector = Bus_MembersInjector.create(Engine_Factory.create());
    }

    @Override
    public void inject(Bus bus) {
        busMembersInjector.injectMembers(bus);
    }

    public static final class Builder {
        private Builder() {
        }

        public BusComponent build() {
            return new DaggerBusComponent(this);
        }
    }
}
           

Bus_MembersInjector,注入类

public final class Bus_MembersInjector implements MembersInjector<Bus> {
  private final Provider<Engine> engineProvider;

  public Bus_MembersInjector(Provider<Engine> engineProvider) {
    assert engineProvider != null;
    this.engineProvider = engineProvider;
  }

  public static MembersInjector<Bus> create(Provider<Engine> engineProvider) {
    return new Bus_MembersInjector(engineProvider);
  }

  @Override
  public void injectMembers(Bus instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.engine = engineProvider.get();
  }

  public static void injectEngine(Bus instance, Provider<Engine> engineProvider) {
    instance.engine = engineProvider.get();
  }
}
           

Engine_Factory,看名字也能看出来是专门负责产生对象的工厂类

public final class Engine_Factory implements Factory<Engine> {
    private static final Engine_Factory INSTANCE = new Engine_Factory();

    @Override
    public Engine get() {
        return new Engine();
    }

    public static Factory<Engine> create() {
        return INSTANCE;
    }
}
           

首先看Dagger2给我们生成的DaggerBusComponent类

我们一步一步往下看

第一步,在我们构造DaggerBusComponent对象是会调用initialize(builder)方法,该方法会创建两个对象Bus_MembersInjector,Engine_Factory;

在Engine_Factory.create()中,会直接返回Engine_Factory单例对象,在Bus_MembersInjector.create()方法,把刚创建的Engine_Factory对象作为成员变量,并初始化DaggerBusComponent中的busMembersInjector成员变量,看到这里还是只知道其中类的关系,还是不知道到底怎么依赖,怎么注入的,别着急,慢慢往下看;

第二步,在调用Bus类中调用DaggerBusComponent的inject(Bus bus),真正调用的是Bus_MembersInjector的inject(),接下来就是关键代码instance.engine = engineProvider.get();这里,直接把engine对象赋值给bus对象的engine变量,这个engine对象来源于Engine_Factory类,而且这个对象是直接由Engine_Factory直接new出来的,至此,该案例分析完毕,哈哈,仰天大笑出门去,我辈岂是蓬蒿人。

这个非常简单的一个例子,如果我们依赖的对象的构造函数需要传参数,或者更复杂的该参数是另一个依赖的对象,接下来,分析一个更复杂的例子

案例2

我们还是以汽车和引擎为例,只不过这次我们的引擎的构造函数需要传入齿轮gear,并且齿轮的构造函数需要传入型号参数

一共有6各类

齿轮类Gear

public class Gear {

    private String code;

    public Gear(String code) {
        this.code=code;
    }

    public void sayCode(){
        System.out.print("齿轮的型号是:"+code);
    }
}
           

引擎类Engine

public class Engine {

    Gear gear;

    public Engine(Gear gear) {
        this.gear=gear;
    }

    public void start(){
        gear.sayCode();
    }
}
           

汽车类

public class Bus {

    @Inject
    Engine engine;

    public Bus(){
        DaggerBusComponent.builder().busModule(new BusModule()).build().inject(this);
    }
}
           

BusModule,用来提供依赖

@Module
public class BusModule {

    @Provides
    Engine provideEngine(Gear gear){
        return new Engine(gear);
    }

    @Provides
    Gear provideGear(){
        return new Gear("G型号齿轮");
    }
}
           

Component,链接依赖需求与依赖提供

@Component(modules ={BusModule.class} )
public interface BusComponent {
    void inject(Bus bus);
}
           

测试类不变

public class TestMain {

    public static void main(String args[]) {
        new Bus().engine.start();
    }
}
           

结果输出如下

齿轮的型号是:G型号齿轮
           

在这个例子中,我们使用到了@module,基本逻辑和上面类似,我们重点来看看@module是怎么起作用的,以及Engine中的Gear对象是怎么注入进去的,废话不多说,下面分析源码

首先调用的是DaggerBusComponent中的initialize()方法

@SuppressWarnings("unchecked")
    private void initialize(final Builder builder) {

        this.provideGearProvider = BusModule_ProvideGearFactory.create(builder.busModule);

        this.provideEngineProvider =
                BusModule_ProvideEngineFactory.create(builder.busModule, provideGearProvider);

        this.busMembersInjector = Bus_MembersInjector.create(provideEngineProvider);
    }
           

在改方法中会产生三个分别类型为Provider<Gear>,Provider<Engine>,MembersInjector<Bus>的成员变量对象,其中Provider<Gear>类型对象包含BusModule对象,Provider<Engine>类型对象包含BusModule对象以及上面产生的Provider<Gear>对象,MembersInjector<Bus>类型对象包含上面产生的Provider<Engine>类型对象

接下来调用的是DaggerBusComponent的inject()方法,其实调用的是Bus_MembersInjector的injectMembers()方法

@Override
    public void injectMembers(Bus instance) {
        if (instance == null) {
            throw new NullPointerException("Cannot inject members into a null reference");
        }
        instance.engine = engineProvider.get();
    }
           

该方法中,直接把engineProvider.get()返回的engine对象赋值给bus对象,完成注入,那engineProvider.get()调用的是什么呢,我们接着往下看,engineProvider.get()其实调用的是BusModule_ProvideEngineFactory类中的get方法

@Override
    public Engine get() {
        return Preconditions.checkNotNull(
                module.provideEngine(gearProvider.get()),
                "Cannot return null from a [email protected] @Provides method");
    }
           

看到了吧,这就回到了Busmodule类了,调用

@Provides
    Engine provideEngine(Gear gear){
        return new Engine(gear);
    }
           

同时关键的地方来了,我们关心的是这个参数gear就是由gearProvider.get()方法提供,这个方法调用BusModule_ProvideGearFactory类中的get()方法,

@Override
    public Gear get() {
        return Preconditions.checkNotNull(
                module.provideGear(), "Cannot return null from a [email protected] @Provides method");
    }
           

也是回到了我们写的BusModule类中,soga,至此我们分析完毕,谢谢大家的收看,我们下次再见。