Dagger2 概述

970 阅读10分钟

写于简书2018-07-20 13:28

Dagger2

Hi~ 我是Dagger2


Dagger2是个什么东西

1.主要功能是依赖注入。 2.在编译时进行依赖注入的框架,而不是通过反射的方式注入。 3.原来有square维护,现在由google维护。为了区分就叫dagger2。

项目地址

github.com/google/dagg…

文档

google.github.io/dagger/

API描述

google.github.io/dagger/api/…

使用Dagger2的好处

  • 解耦合,可以用注入的方式注入依赖对象。
  • 方便测试。

基本概念

注解

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。 可以参考我是陆大旭的GitBook-Android-注解

依赖注入

当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。

可以通过以下几种方式实现
  • 通过接口注入
  • 通过set方法注入
  • 通过构造方法注入
  • 通过Java注解注入

Dagger2就是通过最右一种方法“Java注解注入”完成依赖注入。

如何引入Dagger2

在build.gradle(Project:xxx)中添加如下代码

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

在build.gradle(Module:app)中添加如下代码

apply plugin: 'com.android.application'
apply plugin: 'android-apt'
......
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    /**
     * dragger2
     */
    //使用APT生成工具,生成需要的DI代码
    apt 'com.google.dagger:dagger-compiler:2.5'
    //JSR250的jar包,使用这个和使用glassFish的那个一样,仅为了使用@Inject 和@Named注解
   // provided 'javax.annotation:jsr250-api:1.0'
    //Dagger2 的依赖
    compile 'com.google.dagger:dagger:2.5'
}

几个基本概念

@Inject

此注解用于标记构造函数、方法和字段,也可能使用于静态实例成员。可注解成员可以是任意修饰符(private,package-private,protected,public)。注入顺序:构造函数、字段,然后是方法。父类的字段和方法注入优先于子类的字段和方法,同一类中的字段和方法是没有顺序的。

@Module

此注解用于标记类,Modules类里面的方法专门提供依赖, 在构造类的实例的时候,就知道从哪里去找到需要的依赖。

@Provides

此注解用于标记方法,表示可以通过这个方法获取一个对象,一般用于自定义类中。

@Component

此注解用于标记接口,标示一个注入器。是@Inject和@Module的桥梁,它的主要作用就是连接这两个部分。

简单的例子

代码例子

github.com/iamludaxu/a…

  • 第一步:编写一个Module(FirstModule.class),类需要@Module注解来标识。 Module是提供生成依赖对象的。provideName()提供了一个String对象。注意不能用private修饰。
FirstModule.class
@Module
public class FirstModule {

    private String mName;

    public FirstModule(String name){
        mName = name;
    }

    @Provides
    public String provideName(){
        return mName;
    }
}

  • 第二步:编写一个Component(FirstComponent.class),接口需要@Component注解来标识。 Component注解中需要声明modules(FirstModule.class)
FirstComponent.class
@Component(modules = FirstModule.class)
public interface FirstComponent {

    void inject(Dagger2Activity activity);

}
  • 第三步:编写一个目标类(FirstTargetClass.class),其构造方法@ Inject注解进行标识,表明是一个依赖的构造函数。
FirstTargetClass.class
public class FirstTargetClass {

    private String mName;

    @Inject
    public FirstTargetClass(String name){
        mName = name;
    }

    public String getName(){
        return mName;
    }
}
  • 第四步:使用Dagger进行注入,在Activity中声明一个FirstTargetClass对象,用@Inject注释进行注解。然后调用DaggerXXXXX(DaggerFirstComponent)进行注入。
Dagger2Activity.class
public class Dagger2Activity extends BaseCompatActivity {

    @Inject
    FirstTargetClass mFirstTargetClass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dagger2);

        DaggerFirstComponent.builder().firstModule(new FirstModule("name")).build().inject(this);
    }

}

分析一下代码

四个数据对象

InjectConstructionData.class

/**
 * 在构建函数中注入的对象
 */
public class InjectConstructionData {

    private String mTag;

    public InjectConstructionData() {
        mTag = "InjectConstructionData";
    }

      public String getTag() {
        return mTag;
    }
}

InjectMethodData.class

/**
 * 在方法中注入的对象
 */
public class InjectMethodData {

    private String mTag;

    public InjectMethodData() {
        mTag = "InjectMethodData";
    }

    public String getTag() {
        return mTag;
    }
}

InjectPropertyData.class

/**
 * 在属性中注入的对象
 */
public class InjectPropertyData {

    private  String mTag;

    public InjectPropertyData(){
        mTag = "InjectMemberData";
    }

    public String getTag(){
        return mTag;
    }
}

TestData.class

/**
 * 测试数据
 */
public class TestData {


    private String mName;

    public TestData(String name){
        mName = name;
    }

    public String getName(){
        return mName;
    }
}

FirstModule.class

/**
 * 第一个Module
 */
@Module
public class FirstModule {

    private String mName;

    public FirstModule(String name){
        mName = name;
    }

    /**
     * 提供String对象
     * @return
     */
    @Provides
    public String provideName(){
        return mName;
    }

    /**
     * 提供InjectMethodData对象
     * @return
     */
    @Provides
    public InjectMethodData provideInjectMemberData(){
        return new InjectMethodData();
    }

    /**
     * 提供InjectConstructionData对象
     * @return
     */
    @Provides
    public InjectConstructionData provideInjectConstructionData(){
        return new InjectConstructionData();
    }

    /**
     * 提供InjectPropertyData对象
     * @return
     */
    @Provides
    public InjectPropertyData provideInjectPropertyData(){
        return new InjectPropertyData();
    }
}

SecondModule.class

/**
 * 第二个Module
 */
@Module
public class SecondModule {

    private TestData mTestData;

    public SecondModule(){
        mTestData = new TestData("new SecondModule().TestData()");
    }

    /**
     * 提供TestData对象
     * @return
     */
    @Provides
    TestData providesTestData(){
        return mTestData;
    }

}

FirstTargetClass.class

/**
 *
 * 目标类,需要注入各种对象
 *
 */
public class FirstTargetClass {

    private InjectConstructionData mInjectConstructionData;

    @Inject
    InjectPropertyData mInjectPropertyData;

    @Inject
    TestData mTestData;

    private InjectMethodData mInjectMethodData;

    @Inject
    public FirstTargetClass(InjectConstructionData injectConstructionData){
        mInjectConstructionData = injectConstructionData;
    }

    @Inject
    public void set(InjectMethodData injectMethodData){
        mInjectMethodData = injectMethodData;
    }

    public InjectConstructionData getInjectConstructionData(){
        return mInjectConstructionData;
    }

}

FirstComponent.class

/**
 * Dagger2中的Component向Dagger2Activity中的类注入对象实例
 */
@Component(modules = {FirstModule.class,SecondModule.class})
public interface FirstComponent {

    void inject(Dagger2Activity activity);

}

在build后就会生成DaggerFirstComponent和FirstModule_ProvideInjectPropertyDataFactory、SecondModule_ProvidesTestDataFactory等工厂类。

Dagger2Activity.class

public class Dagger2Activity extends BaseCompatActivity {

    @Inject
    FirstTargetClass mFirstTargetClass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dagger2);

        DaggerFirstComponent.builder()
                .firstModule(new FirstModule("name"))
                .secondModule(new SecondModule())
                .build()
                .inject(this);

    }

}

DaggerFirstComponent.class

public final class DaggerFirstComponent implements FirstComponent {
  private Provider<InjectPropertyData> provideInjectPropertyDataProvider;

  private Provider<TestData> providesTestDataProvider;

  private Provider<InjectMethodData> provideInjectMemberDataProvider;

  private MembersInjector<FirstTargetClass> firstTargetClassMembersInjector;

  private Provider<InjectConstructionData> provideInjectConstructionDataProvider;

  private Provider<FirstTargetClass> firstTargetClassProvider;

  private MembersInjector<Dagger2Activity> dagger2ActivityMembersInjector;

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

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

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

    this.provideInjectPropertyDataProvider =
        FirstModule_ProvideInjectPropertyDataFactory.create(builder.firstModule);

    this.providesTestDataProvider =
        SecondModule_ProvidesTestDataFactory.create(builder.secondModule);

    this.provideInjectMemberDataProvider =
        FirstModule_ProvideInjectMemberDataFactory.create(builder.firstModule);

    this.firstTargetClassMembersInjector =
        FirstTargetClass_MembersInjector.create(
            provideInjectPropertyDataProvider,
            providesTestDataProvider,
            provideInjectMemberDataProvider);

    this.provideInjectConstructionDataProvider =
        FirstModule_ProvideInjectConstructionDataFactory.create(builder.firstModule);

    this.firstTargetClassProvider =
        FirstTargetClass_Factory.create(
            firstTargetClassMembersInjector, provideInjectConstructionDataProvider);

    this.dagger2ActivityMembersInjector =
        Dagger2Activity_MembersInjector.create(firstTargetClassProvider);
  }

  @Override
  public void inject(Dagger2Activity activity) {
    dagger2ActivityMembersInjector.injectMembers(activity);
  }

  public static final class Builder {
    private FirstModule firstModule;

    private SecondModule secondModule;

    private Builder() {}

    public FirstComponent build() {
      if (firstModule == null) {
        throw new IllegalStateException(FirstModule.class.getCanonicalName() + " must be set");
      }
      if (secondModule == null) {
        this.secondModule = new SecondModule();
      }
      return new DaggerFirstComponent(this);
    }

    public Builder firstModule(FirstModule firstModule) {
      this.firstModule = Preconditions.checkNotNull(firstModule);
      return this;
    }

    public Builder secondModule(SecondModule secondModule) {
      this.secondModule = Preconditions.checkNotNull(secondModule);
      return this;
    }
  }
}

解释一下
  • 提供对象实例的XXXProvider工厂类,都继承至Factory,而Factory又继承Provider,在Provider中有个get()方法就是获取对象实例用的。 比如FirstModule_ProvideInjectPropertyDataFactory.class 当调用get()方法的时候其实就是调用FirstModule中的provideInjectPropertyData()方法。
public final class FirstModule_ProvideInjectPropertyDataFactory
    implements Factory<InjectPropertyData> {
  private final FirstModule module;

  public FirstModule_ProvideInjectPropertyDataFactory(FirstModule module) {
    assert module != null;
    this.module = module;
  }

  @Override
  public InjectPropertyData get() {
    return Preconditions.checkNotNull(
        module.provideInjectPropertyData(),
        "Cannot return null from a non-@Nullable @Provides method");
  }

  public static Factory<InjectPropertyData> create(FirstModule module) {
    return new FirstModule_ProvideInjectPropertyDataFactory(module);
  }
}

  • 注入实例的XXXMembersInjector类,继承至MembersInjector,注入的工作都在injectMembers()方法中实现。 比如FirstTargetClass_MembersInjector.class 注入的时候会先获得需要注入的工厂类,然后通过调用injectMembers()方法进行注入。
public final class FirstTargetClass_MembersInjector implements MembersInjector<FirstTargetClass> {
  private final Provider<InjectPropertyData> mInjectPropertyDataProvider;

  private final Provider<TestData> mTestDataProvider;

  private final Provider<InjectMethodData> injectMethodDataProvider;

  public FirstTargetClass_MembersInjector(
      Provider<InjectPropertyData> mInjectPropertyDataProvider,
      Provider<TestData> mTestDataProvider,
      Provider<InjectMethodData> injectMethodDataProvider) {
    assert mInjectPropertyDataProvider != null;
    this.mInjectPropertyDataProvider = mInjectPropertyDataProvider;
    assert mTestDataProvider != null;
    this.mTestDataProvider = mTestDataProvider;
    assert injectMethodDataProvider != null;
    this.injectMethodDataProvider = injectMethodDataProvider;
  }

  public static MembersInjector<FirstTargetClass> create(
      Provider<InjectPropertyData> mInjectPropertyDataProvider,
      Provider<TestData> mTestDataProvider,
      Provider<InjectMethodData> injectMethodDataProvider) {
    return new FirstTargetClass_MembersInjector(
        mInjectPropertyDataProvider, mTestDataProvider, injectMethodDataProvider);
  }

  @Override
  public void injectMembers(FirstTargetClass instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mInjectPropertyData = mInjectPropertyDataProvider.get();
    instance.mTestData = mTestDataProvider.get();
    instance.set(injectMethodDataProvider.get());
  }

  public static void injectMInjectPropertyData(
      FirstTargetClass instance, Provider<InjectPropertyData> mInjectPropertyDataProvider) {
    instance.mInjectPropertyData = mInjectPropertyDataProvider.get();
  }

  public static void injectMTestData(
      FirstTargetClass instance, Provider<TestData> mTestDataProvider) {
    instance.mTestData = mTestDataProvider.get();
  }
}

  • 至于在injectMembers()方法哪里调用的请看FirstTargetClass_Factory.class中的get()方法。injectMembers就是将目标类FirstTargetClass注入依赖对象并返回对象的实例。
public final class FirstTargetClass_Factory implements Factory<FirstTargetClass> {
  private final MembersInjector<FirstTargetClass> firstTargetClassMembersInjector;

  private final Provider<InjectConstructionData> injectConstructionDataProvider;

  public FirstTargetClass_Factory(
      MembersInjector<FirstTargetClass> firstTargetClassMembersInjector,
      Provider<InjectConstructionData> injectConstructionDataProvider) {
    assert firstTargetClassMembersInjector != null;
    this.firstTargetClassMembersInjector = firstTargetClassMembersInjector;
    assert injectConstructionDataProvider != null;
    this.injectConstructionDataProvider = injectConstructionDataProvider;
  }

  @Override
  public FirstTargetClass get() {
    return MembersInjectors.injectMembers(
        firstTargetClassMembersInjector,
        new FirstTargetClass(injectConstructionDataProvider.get()));
  }

  public static Factory<FirstTargetClass> create(
      MembersInjector<FirstTargetClass> firstTargetClassMembersInjector,
      Provider<InjectConstructionData> injectConstructionDataProvider) {
    return new FirstTargetClass_Factory(
        firstTargetClassMembersInjector, injectConstructionDataProvider);
  }
}

  • 最后通过DaggerXXX.inject()将对象实例注入到要用的地方。 在Dagger2Activity.class中mFirstTargetClass就是要注入的对象。
@Inject
FirstTargetClass mFirstTargetClass;
  • 然后通过下面的方式设置FirstModule和SecondModule,并调用inject()方法。
DaggerFirstComponent.builder()
                .firstModule(new FirstModule("name"))
                .secondModule(new SecondModule())
                .build()
                .inject(this);
  • 这样就会调用dagger2ActivityMembersInjector.injectMembers()向Dagger2Activity中注入了FirstTargetClass。
  @Override
  public void inject(Dagger2Activity activity) {
    dagger2ActivityMembersInjector.injectMembers(activity);
  }

多看多理解

其他技术点

单例(Singleton)

在Component中增加Singleton注释 SingletonComponent.class

@Singleton
@Component(modules = SingleModule.class)
public interface SingletonComponent {

    void inject(SingleTest singleTest);
}

SingleModule.class的方法中增加@Singleton注释

@Module
public class SingleModule {

    private int i = 0;

    public SingleModule(){
    }

    @Singleton
    @Provides
    TestData provideSingleTestData(){
        i++;
        return new TestData("name"+i);
    }
}

SingleTest.class

/**
 * 单例目标类
 */
public class SingleTest {

    @Inject
    TestData mTestData1;

    @Inject
    TestData mTestData2;


    SingleTest(){
        DaggerSingletonComponent.builder().singleModule(new SingleModule()).build().inject(this);
    }

    public void print(){
        Logger.i(mTestData1.toString());
        Logger.i(mTestData2.toString());
        Logger.i(mTestData1.getName());
        Logger.i(mTestData2.getName());
    }

}

生成的DaggerSingletonComponent.class

public final class DaggerSingletonComponent implements SingletonComponent {
  private Provider<TestData> provideSingleTestDataProvider;

  ......

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

    this.provideSingleTestDataProvider =
        DoubleCheck.provider(SingleModule_ProvideSingleTestDataFactory.create(builder.singleModule));

    this.singleTestMembersInjector =
        SingleTest_MembersInjector.create(provideSingleTestDataProvider);  }

......

 }

看看看看看这里多了一个里多了一个DoubleCheck.provider()

public final class DoubleCheck<T> implements Provider<T>, Lazy<T> {
  private static final Object UNINITIALIZED = new Object();

  private volatile Provider<T> provider;
  private volatile Object instance = UNINITIALIZED;

  private DoubleCheck(Provider<T> provider) {
    assert provider != null;
    this.provider = provider;
  }

  @SuppressWarnings("unchecked") // cast only happens when result comes from the provider
  @Override
  public T get() {
    Object result = instance;
    if (result == UNINITIALIZED) {
      synchronized (this) {
        result = instance;
        if (result == UNINITIALIZED) {
          result = provider.get();
          /* Get the current instance and test to see if the call to provider.get() has resulted
           * in a recursive call.  If it returns the same instance, we'll allow it, but if the
           * instances differ, throw. */
          Object currentInstance = instance;
          if (currentInstance != UNINITIALIZED && currentInstance != result) {
            throw new IllegalStateException("Scoped provider was invoked recursively returning "
                + "different results: " + currentInstance + " & " + result);
          }
          instance = result;
          /* Null out the reference to the provider. We are never going to need it again, so we
           * can make it eligible for GC. */
          provider = null;
        }
      }
    }
    return (T) result;
  }

  /** Returns a {@link Provider} that caches the value from the given delegate provider. */
  public static <T> Provider<T> provider(Provider<T> delegate) {
    checkNotNull(delegate);
    if (delegate instanceof DoubleCheck) {
      /* This should be a rare case, but if we have a scoped @Binds that delegates to a scoped
       * binding, we shouldn't cache the value again. */
      return delegate;
    }
    return new DoubleCheck<T>(delegate);
  }

  /** Returns a {@link Lazy} that caches the value from the given provider. */
  public static <T> Lazy<T> lazy(Provider<T> provider) {
    if (provider instanceof Lazy) {
      @SuppressWarnings("unchecked")
      final Lazy<T> lazy = (Lazy<T>) provider;
      // Avoids memoizing a value that is already memoized.
      // NOTE: There is a pathological case where Provider<P> may implement Lazy<L>, but P and L
      // are different types using covariant return on get(). Right now this is used with
      // DoubleCheck<T> exclusively, which is implemented such that P and L are always
      // the same, so it will be fine for that case.
      return lazy;
    }
    return new DoubleCheck<T>(checkNotNull(provider));
  }
}

这里会调用一个DoubleCheck(delegate),实现了一个代理类,delegate就是DoubleCheck中的provider,当调用DoubleCheck的get()方法的时候,看里面就实现了单例的。

在Component中需要加@Singleton,否则就会报xxxx(unscoped) may not reference scoped bindings的错。

作用域(Scope)

用来给依赖划定作用域 定义一个作用域CustomScope

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomScope {

}

CustomModule.class

@Module
public class CustomModule {

    private TestData mTestData;

    public CustomModule(String name) {
        mTestData = new TestData(name);
    }

    @CustomScope
    @Provides
    public TestData provideTestData() {
        return mTestData;
    }
}

CustomComponent.class

@CustomScope
@Component(modules = CustomModule.class)
public interface CustomComponent {

    void inject(CustomTest customTest);

    void inject(CustomOtherTest customOtherTest);

}

CustomTest.class

public class CustomTest {

    @Inject
    TestData mTestData;

    public CustomTest(){
        DaggerCustomComponent.builder().customModule(new CustomModule("CustomTest NAME")).build().inject(this);
    }

    public void print(){
        Logger.i(mTestData.toString());
    }
}

CustomOtherTest.class

public class CustomOtherTest {

    @Inject
    TestData mTestData;

    public CustomOtherTest(){
        DaggerCustomComponent.builder().customModule(new CustomModule("CustomTest NAME")).build().inject(this);
    }

    public void print(){
        Logger.i(mTestData.toString());
    }
}

Dagger2Activity.class

public class Dagger2Activity extends BaseCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ......

        CustomTest customTest = new CustomTest();
        customTest.print();//gift.witch.android.ae.dagger2.TestData@42353bc8

        CustomOtherTest customOtherTest = new CustomOtherTest();
        customOtherTest.print();//gift.witch.android.ae.dagger2.TestData@423567b8

    }

}

打印结果...额...不同实例,这个“作用域”作用好像没有任何作用啊! 来我们回头再看看DaggerCustomComponent.class。里面还是多了一个DoubleCheck.provider()方法,和@Singleton注解效果一样。那不是应该是单例的效果吗????

好吧,这个@Singleton是不能实现单例的。实现单例的是XXXComponent被实例化一次,这个才是关键的点。 具体的请参考“Dagger2 使用正确姿势。

限定符(Qualifier)

当一个类的类型不足以标示一个依赖的时候,我们就可以用这个注解。

/**
 * 自定义限定符
 */
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface QualifierType {
    String value() default "";
}

QualifierModule.class

@Module
public class QualifierModule {

    @QualifierType("A")
    @Provides
    TestData provideA(){
        return new TestData("A");
    }

    @QualifierType("B")
    @Provides
    TestData provideB(){
        return new TestData("B");
    }
}

QualifierComponent.class

@Component(modules = QualifierModule.class)
public interface QualifierComponent {

    void inject(QualifierTest qualifierTest);

    @QualifierType("A")
    TestData provideA();

    @QualifierType("B")
    TestData provideB();

}

QualifierTest.class

public class QualifierTest {

    @QualifierType("A")
    @Inject
    TestData mTestDataA;

    @QualifierType("B")
    @Inject
    TestData mTestDataB;

    public QualifierTest(){
        QualifierComponent component = DaggerQualifierComponent.builder().qualifierModule(new QualifierModule()).build();
        component.inject(this);
        TestData testDataA = component.provideA();
        TestData testDataB = component.provideB();

    }

    public void print(){
        Logger.i("TestDataA:"+mTestDataA.getName());
        Logger.i("TestDataB:"+mTestDataB.getName());
    }

}

Dagger2Activity.class

public class Dagger2Activity extends BaseCompatActivity {

    @Inject
    FirstTargetClass mFirstTargetClass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dagger2);

        ......

        QualifierTest qualifierTest = new QualifierTest();
        qualifierTest.print();//TestDataA:A  TestDataB:B

    }

}

这里就分别打印出“TestDataA:A TestDataB:B”

  • 如果在QualifierModule.class中去掉QualifierType注释那么在编译的时候就会报“is bound multiple times”的错误。
  • 默认和用@Named注释来做限定符。

懒加载(Lazy)

LzayModule.class

@Module
public class LzayModule {

    @Provides
    public TestData provideTestData(){
        return new TestData("LzayModule TestData");
    }

}

LazyComponent.class

@Component(modules = LzayModule.class)
public interface LazyComponent {

    void inject(LazyTest lazyTest);

}

LazyTest.class

public class LazyTest {

    @Inject
    Lazy<TestData> mLazy_TestData;

    @Inject
    Provider<TestData> mProvides_TestData;

    public LazyTest(){
        DaggerLazyComponent.builder().lzayModule(new LzayModule()).build().inject(this);
    }


    public void print(){

        Logger.i("TestData one:"+mLazy_TestData.get().toString());//TestData one:gift.witch.android.ae.dagger2.TestData@423ab570
        Logger.i("TestData two:"+mLazy_TestData.get().toString());//TestData two:gift.witch.android.ae.dagger2.TestData@423ab570
        Logger.i("TestData one:"+mProvides_TestData.get().toString());//TestData one:gift.witch.android.ae.dagger2.TestData@423af620
        Logger.i("TestData two:"+mProvides_TestData.get().toString());//TestData two:gift.witch.android.ae.dagger2.TestData@423b1628

    }

}

Dagger2Activity.class

public class Dagger2Activity extends BaseCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dagger2);

        ......

        LazyTest lazyTest = new LazyTest();
        lazyTest.print();

    }

}

看打印的结果怎么就像@Singleton一样,Lazy只初始化一个实例,而Provider会多次初始化实例。原因就是在LazyTest_MembersInjector.class里也有DoubleCheck.lazy()方法:

public final class LazyTest_MembersInjector implements MembersInjector<LazyTest> {
  private final Provider<TestData> mProvides_TestDataAndMLazy_TestDataProvider;

  public LazyTest_MembersInjector(Provider<TestData> mProvides_TestDataAndMLazy_TestDataProvider) {
    assert mProvides_TestDataAndMLazy_TestDataProvider != null;
    this.mProvides_TestDataAndMLazy_TestDataProvider = mProvides_TestDataAndMLazy_TestDataProvider;
  }

  public static MembersInjector<LazyTest> create(
      Provider<TestData> mProvides_TestDataAndMLazy_TestDataProvider) {
    return new LazyTest_MembersInjector(mProvides_TestDataAndMLazy_TestDataProvider);
  }

  @Override
  public void injectMembers(LazyTest instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mLazy_TestData = DoubleCheck.lazy(mProvides_TestDataAndMLazy_TestDataProvider);
    instance.mProvides_TestData = mProvides_TestDataAndMLazy_TestDataProvider;
  }

  public static void injectMLazy_TestData(
      LazyTest instance, Provider<TestData> mLazy_TestDataProvider) {
    instance.mLazy_TestData = DoubleCheck.lazy(mLazy_TestDataProvider);
  }

  public static void injectMProvides_TestData(
      LazyTest instance, Provider<TestData> mProvides_TestData) {
    instance.mProvides_TestData = mProvides_TestData;
  }
}

干货文章

应用例子



我叫陆大旭。

一个懂点心理学的无聊程序员大叔。 看完文章无论有没有收获,记得打赏、关注和点赞!