Written in Jane’s book

Hi ~ I am Dagger2


What is a Dagger2

1. The main function is dependency injection. 2. A framework for dependency injection at compile time, rather than reflection. 3. It was maintained by Square, but now it is maintained by Google. I’ll call it dagger2 just to distinguish.

The project address

Github.com/google/dagg…

The document

google.github.io/dagger/

API description

Google. Making. IO/dagger/API /…

Benefits of using Dagger2

  • Decouple, you can inject dependent objects in the way of injection.
  • Easy to test.

The basic concept

annotations

Annotations, also called metadata. A code level specification. It is a feature introduced in JDK1.5 and later and is on the same level as classes, interfaces, and enumerations. It can be declared in front of packages, classes, fields, methods, local variables, method parameters, etc., used to describe and comment these elements. Please refer to my gitbook-Android

Dependency injection

When one role (perhaps a Java instance, caller) needs the assistance of another role (another Java instance, caller), in traditional programming, it is usually the caller who creates the instance of the caller.

You can do this in the following ways
  • Injection through the interface
  • Injection via the set method
  • Injection via constructor
  • Injection via Java annotations

Dagger2 does dependency injection through the right-most method, Java Annotation Injection.

How to introduce Dagger2

Add the following code to build.gradle(Project: XXX)

Dependencies {classpath 'com. Android. View the build: gradle: 2.3.2' classpath 'com. Neenbedankt. Gradle. Plugins: android - apt: 1.8'}Copy the code

Add the following code to build.gradle(Module:app)

apply plugin: 'com.android.application' apply plugin: 'android-apt' ...... dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) /** * dragger2 */ / use APT to generate DI code APT 'com.google.dagger:dagger- Compiler :2.5' Using this is the same as using glassFish, Provide 'javax.annotation: jSR250-API :1.0' // Compile Dagger2 dependencies only to use @inject and @named annotations // provided 'javax.annotation: jSR250-API :1.0' 'com. Google. Dagger: a dagger: 2.5'}Copy the code

A few basic concepts

@Inject

This annotation is used to mark constructors, methods, and fields, and may also be used for static instance members. Annotable members can be any modifier (private,package-private,protected,public). Injection order: constructor, field, then method. Fields and methods of a parent class take precedence over fields and methods of a subclass; fields and methods in the same class are not ordered.

@Module

This annotation is used to mark up classes. The Modules class has methods that specifically provide dependencies, so you know where to find them when constructing an instance of the class.

@Provides

This annotation is used to mark a method to indicate that an object can be obtained from this method, typically in custom classes.

@Component

This annotation marks the interface and identifies an injector. It is a bridge between @Inject and @Module. Its main function is to connect these two parts.

Simple example

The code example

Github.com/iamludaxu/a…

  • Step 1: Write a Module (firstModule.class) that needs the @Module annotation to identify it.

Module provides for generating dependent objects. ProvideName () provides a String object. Note that you can’t use private.

FirstModule.class
@Module public class FirstModule { private String mName; public FirstModule(String name){ mName = name; } @Provides public String provideName(){ return mName; }}Copy the code
  • Step 2: Write a Component (firstComponent.class). The interface needs the @Component annotation to identify it.

Modules (firstModule.class) should be declared in the Component annotation.

FirstComponent.class
@Component(modules = FirstModule.class)
public interface FirstComponent {

    void inject(Dagger2Activity activity);

}
Copy the code
  • Step 3: Write a target class (firstTargetClass.class) identified by the constructor @Inject annotation as a dependent constructor.
FirstTargetClass.class
public class FirstTargetClass { private String mName; @Inject public FirstTargetClass(String name){ mName = name; } public String getName(){ return mName; }}Copy the code
  • Step 4: Inject with a Dagger and declare a FirstTargetClass object in the Activity annotated with the @Inject annotation. Then call DaggerXXXXX (DaggerFirstComponent) to inject.
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); }}Copy the code

Analyze the code

Four data objects

InjectConstructionData.class

Public Class InjectConstructionData {private String mTag; public InjectConstructionData() { mTag = "InjectConstructionData"; } public String getTag() { return mTag; }}Copy the code

InjectMethodData.class

Public class InjectMethodData {private String mTag; public InjectMethodData() { mTag = "InjectMethodData"; } public String getTag() { return mTag; }}Copy the code

InjectPropertyData.class

/** * Public class InjectPropertyData {private String mTag; public InjectPropertyData(){ mTag = "InjectMemberData"; } public String getTag(){ return mTag; }}Copy the code

TestData.class

/** * public class TestData {private String mName; public TestData(String name){ mName = name; } public String getName(){ return mName; }}Copy the code

FirstModule.class

/** * @module public class FirstModule {private String mName; public FirstModule(String name){ mName = name; } /** * Provides a String object * @return */ @provides public String provideName(){return mName; } /** * Provides InjectMethodData * @return */ @provides public InjectMethodData provideInjectMemberData(){return new InjectMethodData(); } / * * * * @ InjectConstructionData target return * / @ Provides public InjectConstructionData provideInjectConstructionData () {  return new InjectConstructionData(); } / * * * * @ InjectPropertyData target return * / @ Provides public InjectPropertyData provideInjectPropertyData () {return new InjectPropertyData(); }}Copy the code

SecondModule.class

/** * SecondModule */ @module public class SecondModule {private TestData mTestData; public SecondModule(){ mTestData = new TestData("new SecondModule().TestData()"); } /** * Provides TestData * @return */ @provides TestData providesTestData(){return mTestData; }}Copy the code

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; }}Copy the code

FirstComponent.class

/ * * * Dagger2 objects into a class instance of the Component to Dagger2Activity * / @ Component modules (= {FirstModule. Class, SecondModule class}) public  interface FirstComponent { void inject(Dagger2Activity activity); } in the build is generated after DaggerFirstComponent and FirstModule_ProvideInjectPropertyDataFactory, SecondModule_ProvidesTestDataFactory factory class, etc.Copy the code

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); }}Copy the code

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; }}}Copy the code
explain
  • The XXXProvider Factory class that provides object instances inherits from Factory, which in turn inherits from Provider, where a get() method is used to get object instances.

Such as FirstModule_ProvideInjectPropertyDataFactory. Class when calling the get () method is invoked when the provideInjectPropertyData FirstModule () method.

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);
  }
}

Copy the code
  • The XXXMembersInjector class that injects the instance, inherits from MembersInjector, and does all the work in injectMembers().

For example, firstTargetClass_membersinejector. Class gets the factory class that needs to be injected and then injectMembers() is called.

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(); }}Copy the code
  • See the get() method in firstTargetClass_factory.class for details about where injectMembers() is called. InjectMembers are instances that inject the target class FirstTargetClass into dependent objects and return them.
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); }}Copy the code
  • Finally, use daggerxxx.inject () to inject the object instance to the desired place.

In dagger2Activity.class, mFirstTargetClass is the object to inject.

@Inject
FirstTargetClass mFirstTargetClass;
Copy the code
  • Then set FirstModule and SecondModule as follows and call the Inject () method.
DaggerFirstComponent.builder()
                .firstModule(new FirstModule("name"))
                .secondModule(new SecondModule())
                .build()
                .inject(this);
Copy the code
  • This is called dagger2ActivityMembersInjector. InjectMembers () to the injected FirstTargetClass Dagger2Activity.
  @Override
  public void inject(Dagger2Activity activity) {
    dagger2ActivityMembersInjector.injectMembers(activity);
  }
Copy the code

See and understand

Other technical points

Singleton

Add the Singleton annotation singletonComponent.class to Component

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

    void inject(SingleTest singleTest);
}
Copy the code

Add the @singleton annotation to the singleModule. class method

@Module public class SingleModule { private int i = 0; public SingleModule(){ } @Singleton @Provides TestData provideSingleTestData(){ i++; return new TestData("name"+i); }}Copy the code

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()); }}Copy the code

The generated 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); }... }Copy the code

Look at that. Look at that. Look at that. Look at that.

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)); }}Copy the code

This is going to call a DoubleCheck(delegate), which implements a delegate class, and the delegate is the provider in DoubleCheck, and when you call the Get () method of DoubleCheck, look inside, you implement a singleton.

@singleton (Component) bindings (XXXX (unscoped) may not reference scoped Bindings (Bindings))

Scope

Define a scope, CustomScope, for scoping dependencies

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

}
Copy the code

CustomModule.class

@Module public class CustomModule { private TestData mTestData; public CustomModule(String name) { mTestData = new TestData(name); } @CustomScope @Provides public TestData provideTestData() { return mTestData; }}Copy the code

CustomComponent.class

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

    void inject(CustomTest customTest);

    void inject(CustomOtherTest customOtherTest);

}
Copy the code

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()); }}Copy the code

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()); }}Copy the code

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 } }Copy the code

Print results… Er… Depending on the instance, this “scope” effect seems to have no effect at all. We see DaggerCustomComponent back to class. There’s still a doublecheck.provider () method inside, which works just like the @Singleton annotation. Isn’t that supposed to be a singleton effect ????

Well, this @singleton is not going to implement a Singleton. The implementation of the singleton is that XXXComponent is instantiated once, which is the key point. For details, see “Dagger2 Use Proper posture.”

Qualifier

We use this annotation when a class’s type is insufficient to indicate a dependency.

@qualifier @Retention(retentionPolicy.runtime) public @interface QualifierType {String value() default ""; }Copy the code

QualifierModule.class

@Module public class QualifierModule { @QualifierType("A") @Provides TestData provideA(){ return new TestData("A"); } @QualifierType("B") @Provides TestData provideB(){ return new TestData("B"); }}Copy the code

QualifierComponent.class

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

    void inject(QualifierTest qualifierTest);

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

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

}
Copy the code

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 ()); }}Copy the code

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}}Copy the code

So I’m going to print “TestDataA: A TestDataB: B”

  • If the QualifierType comment is removed from the qualifierModule. class, you will get the “is bound multiple times” error at compile time.
  • Default and use @named annotations for qualifiers.

Lazy loading

LzayModule.class

@Module public class LzayModule { @Provides public TestData provideTestData(){ return new TestData("LzayModule TestData"); }}Copy the code

LazyComponent.class

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

    void inject(LazyTest lazyTest);

}
Copy the code

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 } }Copy the code

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(); }}Copy the code

Just like @Singleton,Lazy initializes only one instance, whereas Provider initializes instances multiple times. The reason is that there is also a DoubleCheck. Lazy () method in LazyTest_MembersInjector. Class:

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;
  }
}

Copy the code

Dry articles

  • Dagger2Getting started, from a beginner’s point of view

  • Dagger2

  • DI Framework Dagger2 Systematic Learning – not to be missed dry goods

  • Build android framework from scratch (6)

Application example

  • Google MVP Dagger2

  • MVPArms Dagger2+Rxjava+Retrofit



My name is Lu Daxu.

A boring programmer who knows something about psychology. Tip, follow and like the article whether or not you get anything from it!