深入浅出依赖注入框架Dagger2

目录

    • 目录
    • 依赖注入
    • 依赖注入实现的三种方式
        • 1. 构造注入
        • 2. 属性注入
        • 3. 接口注入
    • Dagger2
    • Dagger2的引入
    • 不带Module的Inject方式(Inject+Component)
    • 带Module的Inject方式(Inject+Component+Module)
    • Module带参数
    • Scope作用域
    • Qualifier方法
    • Component间依赖的两种方式
        • a)Dependence方式
        • b)SubComponent方式
        • 两种方式的比较
    • 懒加载与重加载
    • 总结
    • 参考资料

依赖注入

依赖注入(DI)是控制反转(Inversion of Control,IoC)的一种重要方式,IoC是将依赖对象的创建和绑定通过被依赖对象类的外部来实现。依赖注入提供一种机制,将需要依赖对象的引用传递给被依赖对象。它是面向对象的一种设计模式,其目的是为了降低耦合。举个栗子:

public class Person {
    Decorate decorate;
    public Person(){
        decorate = new Decorate(jacket,shoe);
    }
}

这里的Person对象的初始化为实例化Decorate,如果Decorate类实例化参数增加,则必须对Person对象初始化进行修改。如果还有其他类的也是按照这种方式创建Decorate类,那么就需要修改多处,这违背了单一职责原则和开闭原则。因此需要引入依赖注入来解决这个问题。

依赖注入实现的三种方式

下面将会介绍三种简单的依赖注入方式,一般依赖注入的框架的基本原理基本一样,避免在被依赖对象中直接实例化依赖对象,而是通过其他方式引入。根据依赖注入的定义,下面例子中依赖对象为Decorate,被依赖对象为Person。

1. 构造注入

通过构造函数直接注入

public class Person {
    private Decorate decorate;
    public Person(Decorate decorate){
        this.decorate = decorate;
    }
}

2. 属性注入

通过属性来传递依赖即通过set方法

public class Person {
    private Decorate decorate;
    public void setPerson(Decorate decorate){
        this.decorate = decorate;
    }
}

3. 接口注入

相比前面两种方法,接口注入的方式显得有些复杂。需要先定义一个接口,包含一个设置依赖对象的方法,然后让被依赖对象继承并实现这个接口。

public interface Inject{
    void inject(Decorate decorate)
}
public class Person implements Inject{
    private Decorate decorate;
    @Override
    public void inject(Decorate decorate) {
        this.decorate = decorate;
    }
}

Dagger2

在github上Dagger2是这样定义的,Dagger2是一个Android和java快速依赖注入框架。Dragger2是在编译时注解的方式实现依赖注入,是Dagger的升级版,取消了反射的使用。通过@Component的接口替代ObjectGraph/Injector,从而使代码更精简。早期的一些注入框架是通过反射机制在运行时完成注入的工作,而反射对性能影响很大,所以现在基本上是采用编译时通过工具生成相应的类文件实现的。

Dagger2的引入

完成Dagger2的依赖方式有两种,分别为annotationProcessor和android-apt。android-apt是开发者自己开发的apt框架,随着谷歌Android Gradle2.2插件的发布,插件提供了annotationProcessor来替换android-apt,自此基本上都使用annotationProcessor。
项目中通过annotationProcessor的方式进行依赖,在app的build.gradle添加:

implementation 'com.google.dagger:dagger:2.10'
annotationProcessor "com.google.dagger:dagger-compiler:2.10"
implementation "org.glassfish:javax.annotation:10.0-b28"

不带Module的Inject方式(Inject+Component)

1.定义一个Person类,在构造函数前加上@Inject,表明支持依赖注入

public class Person {
    @Inject
    public Person(){
    }
    public String getSex(){
        return "male";
    }
}

2.定义接口MainActivityComponent,在接口前添加@Component,定义相应的抽象方法,方法的参数为需要注入对象的真实所在的类,方法名一般为Inject。Component可以理解为Person(依赖对象)和MainActivity(被依赖对象)之间的桥梁

@Component
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

3.对项目进行Rebuild,Dagger2框架会根据MainActivityComponent自动生成DaggerMainActivityComponent(命名规则Dagger+Component名称)。在MainActivity声明Person对象,并用@Inject的注解,然后通过DaggerMainActivityComponent注入Person对象。

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    @Inject
    Person person;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainActivityComponent.builder().build().inject(this);
        Log.d(TAG,person.getSex());
    }
}

11:32:53.851 29222-29222/com.skyblue.dragger2 D/MainActivity: male

可以看出MainActivity成功注入了Person类,下面分析是如何注入Person类的:
打开DaggerMainActivityComponent,可以看出其对应的路径\app\build\generated\source\apt\debug,在其目录下同时也有其他两个类Person_Factory,MainActivity_MembersInjector。
在MainActivity中DaggerMainActivityComponent.builder().build().inject(this)将会实例化DaggerMainActivityComponent,在实例化的过程中调用了initialize函数,而该函数的作用是调用了MainActivity_MembersInjector的create函数。再看类中的Inject函数,该类继承了MainActivityComponent。可以猜测mainActivityMembersInjector.injectMembers(activity)完成了Person类的注入。

package com.skyblue.dragger2;

import dagger.MembersInjector;
import javax.annotation.Generated;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerMainActivityComponent implements MainActivityComponent {
  private MembersInjector mainActivityMembersInjector;

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

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

  public static MainActivityComponent create() {
    return new Builder().build();
  }

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

    this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create());
  }

  @Override
  public void inject(MainActivity activity) {
    mainActivityMembersInjector.injectMembers(activity);
  }

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

    public MainActivityComponent build() {
      return new DaggerMainActivityComponent(this);
    }
  }
}

MainActivity_MembersInjector类是实例化Person类的关键,也是注入具体的实现方式。在上面讨论调用到该类的create的函数,create函数传入的参数为Person_Factory.create,inject调用了mainActivityMembersInjector.injectMembers(activity)即调用了instance.person = personProvider.get();

package com.skyblue.dragger2;

import dagger.MembersInjector;
import javax.annotation.Generated;
import javax.inject.Provider;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class MainActivity_MembersInjector implements MembersInjector {
  private final Provider personProvider;

  public MainActivity_MembersInjector(Provider personProvider) {
    assert personProvider != null;
    this.personProvider = personProvider;
  }

  public static MembersInjector create(Provider personProvider) {
    return new MainActivity_MembersInjector(personProvider);
  }

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

  public static void injectPerson(MainActivity instance, Provider personProvider) {
    instance.person = personProvider.get();
  }
}

Person_Factory是对应Person类中在构造函数前添加@Inject注解,由Dragger2自动生成的对用的工厂类,用于实例化对象,来提供给需要的类。Person_Factory.create()的函数实例化了Factory,mainActivityMembersInjector.injectMembers(activity)调用的instance.person = personProvider.get()从而具体实例化了Person类。

package com.skyblue.dragger2;

import dagger.internal.Factory;
import javax.annotation.Generated;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class Person_Factory implements Factory<Person> {
  private static final Person_Factory INSTANCE = new Person_Factory();

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

  public static Factory create() {
    return INSTANCE;
  }

}

MainActivity_MembersInjector的create函数传入的对象类型为Provider,而Person_Factory.create()的类型为Factory,那么它们之前一定是一种继承的关系。通过查看Factory继承了Provider。

package dagger.internal;

import dagger.Provides;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Scope;

/**
 * An {@linkplain Scope unscoped} {@link Provider}. While a {@link Provider} may apply
 * scoping semantics while providing an instance, a factory implementation is guaranteed to exercise
 * the binding logic ({@link Inject} constructors, {@link Provides} methods) upon each call to
 * {@link #get}.
 *
 * 

Note that while subsequent calls to {@link #get} will create new instances for bindings such * as those created by {@link Inject} constructors, a new instance is not guaranteed by all * bindings. For example, {@link Provides} methods may be implemented in ways that return the same * instance for each call. * * @author Gregory Kick * @since 2.0 */ public interface Factory extends Provider { }

通过上面的分析基本清楚了,Person是如何在MainActivity注入的。总结一下:
首先在定义了Person类中注解@Inject由Dagger2生成了其对应的工厂类Factory,再定义注入的Component接口,声明注入的方法,Dagger2自动生成了DaggerMainActivityComponent,并在其类中调用了MainActivity_MembersInjector的inject方法,该方法封装了通过Factory 的get方法实现了对Person的实例化注入。

带Module的Inject方式(Inject+Component+Module)

在上面的Person中是自己定义的类,如果是某个库中的类,则是不能够去该类中添加@Inject注解了,那么注入这种类该如何注入呢,这个时候就需要Module。Module可以理解为对对象的实例化,向Component的提供依赖对象。下面以Person类为对象说明:
1.创建一个MainModule,并用@Module注解,在类中提供Person对象的方法并用@Provider注解(取消之前Person类中的@Inject注解)

@Module
public class MainModule {
    @Provides
    public Person providePerson(){
        return new Person();
    }
}

2.修改MainActivityComponent,为其添加Module应用,来说明其可能需要用到MainModule中提供的对象。

@Component(modules = MainModule.class)
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

3.MainActivity保持不变

16:11:20.927 7148-7148/com.skyblue.dragger2 D/MainActivity: male

可以看出和上面的例子结果一样,主要不同的是增加了MainModule。Dagger2自动生成的类中没有了Person_Factory,而是MainModule_ProvidePersonFactory类。可以看出该类和Person_Factory本质上是一样的,提供依赖对象。如果MainModule中还有其它的Providers那么会生成对应数量的MainModule_ProvideXXFactory类,其类中会提供对应数量的get方法。

package com.skyblue.dragger2;

import dagger.internal.Factory;
import dagger.internal.Preconditions;
import javax.annotation.Generated;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class MainModule_ProvidePersonFactory implements Factory {
  private final MainModule module;

  public MainModule_ProvidePersonFactory(MainModule module) {
    assert module != null;
    this.module = module;
  }

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

  public static Factory create(MainModule module) {
    return new MainModule_ProvidePersonFactory(module);
  }
}

DaggerMainActivityComponent基本上保持不变。

package com.skyblue.dragger2;

import dagger.MembersInjector;
import dagger.internal.Preconditions;
import javax.annotation.Generated;
import javax.inject.Provider;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerMainActivityComponent implements MainActivityComponent {
  private Provider providePersonProvider;

  private MembersInjector mainActivityMembersInjector;

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

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

  public static MainActivityComponent create() {
    return new Builder().build();
  }

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

    this.providePersonProvider = MainModule_ProvidePersonFactory.create(builder.mainModule);

    this.mainActivityMembersInjector = MainActivity_MembersInjector.create(providePersonProvider);
  }

  @Override
  public void inject(MainActivity activity) {
    mainActivityMembersInjector.injectMembers(activity);
  }

  public static final class Builder {
    private MainModule mainModule;

    private Builder() {}

    public MainActivityComponent build() {
      if (mainModule == null) {
        this.mainModule = new MainModule();
      }
      return new DaggerMainActivityComponent(this);
    }

    public Builder mainModule(MainModule mainModule) {
      this.mainModule = Preconditions.checkNotNull(mainModule);
      return this;
    }
  }
}

Module带参数

一般情况下大多数的类都需要传入参数的,下面看下带参数的类的实例化是如何的。
1. 修改Person类

public class Person {

    private int age ;
    public Person(int age){
        this.age = age;
    }
    public String getSex(){
        return "male";
    }

    public int getAge(){
        return age;
    }

2.将Person类的age参数传入

@Module
public class MainModule {
    int age;
    public MainModule(int age){
        this.age = age;
    }
    @Provides
    public Person providePerson(){
        return new Person(age);
    }
    @Provides
    public Decorate providerDecorate(){
        return new Decorate();
    }
}

3.在MainActivity中设置MainModule对象的参数

DaggerMainActivityComponent.builder().mainModule(new MainModule(19)).build().inject(this);

16:50:37.343 8787-8787/? D/MainActivity: 19

需要注意的是在无参数的时候,DaggerMainActivityComponent会提供create方法,但是有参数时,只有build方法,因为需要传入MainModule对象。一般建议通过provide方法提供参数,主要是解耦和增加代码的可读性。

@Module
public class MainModule {
    int age;
    public MainModule(int age){
        this.age = age;
    }

    @Provides
    public int provideAge(){
        return age;
    }

    @Provides
    public Person providePerson(){
        return new Person(age);
    }
    @Provides
    public Decorate providerDecorate(){
        return new Decorate();
    }
}

Module中不能出现参数和返回参数一致的情况,否则会导致死循环。如:

@Provides
public int provideAge(int age){
    return age;
}

Scope作用域

通过Singleton注解的例子来了解作用域,在MainActivity中注入两个Person对象

@Inject
Person person1;
@Inject
Person person2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DaggerMainActivityComponent.builder().mainModule(new MainModule(19)).build().inject(this);
    Log.d(TAG,person1+"");
    Log.d(TAG,person2+"");

}

17:09:29.532 9503-9503/? D/MainActivity: com.skyblue.dragger2.Person@29c76f
com.skyblue.dragger2.Person@b67ec7c

可以看到有两个不同的对象,那么怎么才能够让他们保持单例呢?这时就需要Singleton注解,那么注解放在什么地方呢?主要要放在两个地方。
1.提供Person对象的地方
需要注意的是@Inject和@Singleton不能同时使用,所以只能放在Module中。

@Singleton 
@Provides
public Person providePerson(){
    return new Person(age);
}

2.依赖对象和被依赖对象的桥梁component

@Singleton
@Component(modules = MainModule.class)
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

17:17:40.525 10490-10490/com.skyblue.dragger2 D/MainActivity: com.skyblue.dragger2.Person@29c76f
com.skyblue.dragger2.Person@29c76f

添加Singleton注解前后主要的不同是在providePersonProvider获取的不同,添加后添加了DoubleCheck.provider检查。

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

  this.providePersonProvider =
      DoubleCheck.provider(MainModule_ProvidePersonFactory.create(builder.mainModule));

  this.mainActivityMembersInjector = MainActivity_MembersInjector.create(providePersonProvider);
}

/** Returns a {@link Provider} that caches the value from the given delegate provider. */
public static  Provider provider(Provider 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(delegate);
}

如果添加了scope类型的注解后,将会返回之前的缓存对象。
Singleton的注解定义为:

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}

将上面的Singleton换成SingletonTest,引用@SingletonTest注释,效果一样。还要一点需要注意的是Scope取决于Component的周期长短,如果在应用的Application中注入,那么周期是整个应用程序,如果只是MainActivity那么周期只是Activity的周期。如果在两个Component的中注入了同一个对象,那么这两个对象即使设定了Scope,并不是同一个对象,因为Component的之间是相互独立的。

Qualifier方法

当Module中有两个返回值相同的方法时,可以使用@Name区分,

@Named("two")
@Provides
String providesString1() {
    return "test1";
}

@Named("three")
@Provides
String providesString2() {
    return "test2";
} 

// MainActivity 
@Named("two") 
@Inject String test1; 
@Named("three") 
@Inject String test2;

Qualifier和Scope一样,因此我们也可以自定义注解替代@Name

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {

    /** The name. */
    String value() default "";
}

Component间依赖的两种方式

当某个依赖对象在多个Component都需要时,没有必要在每个Component的中注入依赖。Component间的依赖有两种方式dependence和subcomponent,有些像组合和继承的关系。

a)Dependence方式

1.定义一个类对象

public class Decorate {
    public Decorate(){
    }
}

2.定义一个全局的Component

@Component(modules = AppModule.class)
public interface AppComponent {
    Decorate providersDecorate();
}

3.定义Module提供对象

@Module
public class AppModule {
    Context context;
    public AppModule(Context context){
        this.context = context;
    }

    @Provides
    Context providersContext(){
        return  context;
    }

    @Provides
    Decorate providersDecorate(){
        return new Decorate();
    }
}

4.在MainActivityComponent中添加其他Component的依赖

@Singleton
@Component(dependencies = AppComponent.class,modules = MainModule.class)
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

5.在MainActivity中注入,通过AppComponent将对象提供给MainActivity

public class MainActivity extends AppCompatActivity {

    @Inject
    Decorate decorate;

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

        AppComponent appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
        DaggerMainActivityComponent.builder().appComponent(appComponent).mainModule(new MainModule(10)).build().inject(this);

        Log.d("dragger2",decorate+"");
    }
}

07-09 19:10:11.604 23155-23155/? D/dragger2: com.skyblue.dragger2.Decorate@db9ce1a

再分析下生成的文件,这里主要看下DaggerMainActivityComponent,看如何获取到Decorate对象的

package com.skyblue.dragger2;

import dagger.MembersInjector;
import dagger.internal.Preconditions;
import javax.annotation.Generated;
import javax.inject.Provider;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerMainActivityComponent implements MainActivityComponent {
  private Provider providersDecorateProvider;

  private MembersInjector mainActivityMembersInjector;

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

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

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

    this.providersDecorateProvider =
        new com_skyblue_dragger2_AppComponent_providersDecorate(builder.appComponent);

    this.mainActivityMembersInjector =
        MainActivity_MembersInjector.create(providersDecorateProvider);
  }

  @Override
  public void inject(MainActivity activity) {
    mainActivityMembersInjector.injectMembers(activity);
  }

  public static final class Builder {
    private AppComponent appComponent;

    private Builder() {}

    public MainActivityComponent build() {
      if (appComponent == null) {
        throw new IllegalStateException(AppComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerMainActivityComponent(this);
    }

    /**
     * @deprecated This module is declared, but an instance is not used in the component. This
     *     method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
     */
    @Deprecated
    public Builder mainModule(MainModule mainModule) {
      Preconditions.checkNotNull(mainModule);
      return this;
    }

    public Builder appComponent(AppComponent appComponent) {
      this.appComponent = Preconditions.checkNotNull(appComponent);
      return this;
    }
  }

  private static class com_skyblue_dragger2_AppComponent_providersDecorate
      implements Provider {
    private final AppComponent appComponent;

    com_skyblue_dragger2_AppComponent_providersDecorate(AppComponent appComponent) {
      this.appComponent = appComponent;
    }

    @Override
    public Decorate get() {
      return Preconditions.checkNotNull(
          appComponent.providersDecorate(),
          "Cannot return null from a non-@Nullable component method");
    }
  }
}

在initialize中还是通过provider对象的方式来获取AppComponent依赖提供的对象。可以看到在获取providersDecorateProvider时,新建了一个内部静态类,命名方式为包名+依赖组件名+提供依赖对象的方法名,传入的参数为通过建造者模式获取的组件对象。而是的操作和前面的基本相同。通过生成的代码可以知道AppComponent只是相当于对象的转发,通过这种方式被其他的Component依赖。

b)SubComponent方式

1.修改Dependence方式中AppComponent,不再提供依赖对象,而是变成子Component,直接使用AppModule完成对象的注入。

@Component(modules = AppModule.class)
public interface AppComponent {
    MainActivityComponent acitvityComponet();
}

2.修改Dependence方式中的MainActivityComponent

@Singleton
@Subcomponent (modules = MainModule.class)
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

3.在MainActivity中添加依赖

public class MainActivity extends AppCompatActivity {

    @Inject
    Decorate decorate;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerAppComponent.builder().appModule(new AppModule(this)).build().acitvityComponet().inject(this);
        Log.d("dragger2",decorate+"");
    }
}

07-09 19:45:01.862 23864-23864/? D/dragger2: com.skyblue.dragger2.Decorate@db9ce1a

再看生成的代码,这里主要不同的是DaggerAppComponent

package com.skyblue.dragger2;

import dagger.MembersInjector;
import dagger.internal.Preconditions;
import javax.annotation.Generated;
import javax.inject.Provider;

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerAppComponent implements AppComponent {
  private Provider providersDecorateProvider;

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

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

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

    this.providersDecorateProvider = AppModule_ProvidersDecorateFactory.create(builder.appModule);
  }

  @Override
  public MainActivityComponent acitvityComponet() {
    return new MainActivityComponentImpl();
  }

  public static final class Builder {
    private AppModule appModule;

    private Builder() {}

    public AppComponent build() {
      if (appModule == null) {
        throw new IllegalStateException(AppModule.class.getCanonicalName() + " must be set");
      }
      return new DaggerAppComponent(this);
    }

    public Builder appModule(AppModule appModule) {
      this.appModule = Preconditions.checkNotNull(appModule);
      return this;
    }
  }

  private final class MainActivityComponentImpl implements MainActivityComponent {
    private MembersInjector mainActivityMembersInjector;

    private MainActivityComponentImpl() {
      initialize();
    }

    @SuppressWarnings("unchecked")
    private void initialize() {

      this.mainActivityMembersInjector =
          MainActivity_MembersInjector.create(DaggerAppComponent.this.providersDecorateProvider);
    }

    @Override
    public void inject(MainActivity activity) {
      mainActivityMembersInjector.injectMembers(activity);
    }
  }
}

代码中DaggerAppComponent中为子Component生成了一个内部类,命名方式为子Componet名称+Impl,通过AppComponent提供的接口,来获取该内部对象。在initialize中通过providersDecorateProvider(AppModule生成)最后实现注入对象。

两种方式的比较

两种方式都可以实现Component之间的依赖对象关联,选择哪种方式进行关联,需要根据具体的情形。Dependencies像类中的组合关系,subcomponent像类中的继承关系。
两者在Scope时需要注意:
Dependencies中两个有依赖关系的Component不能有相同的@Scope注解而subcomponent则可以。
两种方式的比较
Dependencies
特点:
可以知道对应Component的所依赖的Component
每个Component都会生成对应的DaggerXxxComponent
被依赖的Component会为依赖Component提供对象的获取
使用依赖Component传入被依赖Component完成注入
注意
被依赖Component中没有显式的提供依赖无法完成注入
Subcomponent
特点
父Component可以管理子Component
只有父Component会生成DaggerXxxComponent
默认可以获取到父子两个Component使用到的Module所提供的对象
使用父Component并选择指定的子Component完成注入

懒加载与重加载

懒加载:通过调用get方法时才创建对象,以后获取的对象为同一对象
重加载:通过调用get方法时会强制重新创建对象,对象是否重建取决于Module的实现方式(@Scope注释)

public class MainActivity extends AppCompatActivity {

    @Inject
    Lazy decorateLazy;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerAppComponent.builder().appModule(new AppModule(this)).build().acitvityComponet().inject(this);
        Decorate decorate = decorateLazy.get();

    }
}

再看apt生成的代码,主要看注入部分的代码

public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final Provider decorateLazyProvider;

  public MainActivity_MembersInjector(Provider decorateLazyProvider) {
    assert decorateLazyProvider != null;
    this.decorateLazyProvider = decorateLazyProvider;
  }

  public static MembersInjector create(Provider decorateLazyProvider) {
    return new MainActivity_MembersInjector(decorateLazyProvider);
  }

  @Override
  public void injectMembers(MainActivity instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.decorateLazy = DoubleCheck.lazy(decorateLazyProvider);
  }

  public static void injectDecorateLazy(
      MainActivity instance, Provider decorateLazyProvider) {
    instance.decorateLazy = DoubleCheck.lazy(decorateLazyProvider);
  }
}

在该类中injectMembers方法使用了DoubleCheck.lazy处理后得到Lazy对象,而一般情况是通过provide的get方法获取到对象。下面是DoubleCheck.lazy的代码

/** Returns a {@link Lazy} that caches the value from the given provider. */
public static  Lazy lazy(Provider provider) {
  if (provider instanceof Lazy) {
    @SuppressWarnings("unchecked")
    final Lazy lazy = (Lazy) provider;
    // Avoids memoizing a value that is already memoized.
    // NOTE: There is a pathological case where Provider

may implement Lazy, but P and L // are different types using covariant return on get(). Right now this is used with // DoubleCheck 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(checkNotNull(provider)); }

/**
 * A {@link Lazy} and {@link Provider} implementation that memoizes the value returned from a
 * delegate using the double-check idiom described in Item 71 of Effective Java 2.
 */
public final class DoubleCheck<T> implements Provider<T>, Lazy<T> {
  private static final Object UNINITIALIZED = new Object();

  private volatile Provider provider;
  private volatile Object instance = UNINITIALIZED;

  private DoubleCheck(Provider 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 + ". This is likely "
                + "due to a circular dependency.");
          }
          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;
  }

可以看出DoubleCheck.lazy实例化了一个DoubleCheck对象,再封装Provider通过双重检查机制来实现单例。

总结

Inject主要是标注需要注入的对象
Component主要是提供注入对象的入口
Module主要是在对象类中不能添加Inject的标注时,提供方法,对象,返回值
Scope主要是用于作用域的标注,通过Singleton或者自定义注解实现单例
Component间相互依赖的两种方式dependencies和subcomponent,类似组合和继承的关系
懒加载(Lazy)和重加载(Provider):懒加载是有Provider封装好的DoubleCheck对象

参考资料

https://github.com/google/dagger
https://www.jianshu.com/p/b266314a97db?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
http://alighters.com/blog/2016/04/15/dagger2-indepth-understanding/
https://google.github.io/dagger/api/2.0/index.html
http://www.cnblogs.com/liuhaorain/p/3747470.html
https://www.jianshu.com/p/22c397354997/

你可能感兴趣的:(Android进阶)