再探Dagger2

2018-06-09  本文已影响9人  一个大西瓜CPI

先看Dagger2的注解


image

1.Inject注解

//空参构造
public class PersonBean {

    String name;

    @Inject
    public PersonBean() {
    }

}

//生成的工厂类
public final class PersonBean_Factory implements Factory<PersonBean> {
  private static final PersonBean_Factory INSTANCE = new PersonBean_Factory();

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

  public static Factory<PersonBean> create() {
    return INSTANCE;
  }
}
//有参构造
public class PersonBean {

    String name;

    @Inject
    public PersonBean(String name) {
        this.name = name;
    }
}

生成的工厂类
public final class PersonBean_Factory implements Factory<PersonBean> {
  private final Provider<String> nameProvider;

  public PersonBean_Factory(Provider<String> nameProvider) {
    assert nameProvider != null;
    this.nameProvider = nameProvider;
  }

  @Override
  public PersonBean get() {
    return new PersonBean(nameProvider.get());
  }

  public static Factory<PersonBean> create(Provider<String> nameProvider) {
    return new PersonBean_Factory(nameProvider);
  }
}

// 在person类中注入变量
public class Clothes {

    String color;

    @Inject
    public Clothes(String color) {
        this.color = color;
    }
}

public class PersonBean {

    String name;
    @Inject
    Clothes clothes;

    @Inject
    public PersonBean(String name) {
        this.name = name;
    }
}

此时在apt目录下多生成了一个PersonBean_MembersInjector文件,如图:


dagger_1.PNG
public final class PersonBean_MembersInjector implements MembersInjector<PersonBean> {
  private final Provider<Clothes> clothesProvider;

  public PersonBean_MembersInjector(Provider<Clothes> clothesProvider) {
    assert clothesProvider != null;
    this.clothesProvider = clothesProvider;
  }

  public static MembersInjector<PersonBean> create(Provider<Clothes> clothesProvider) {
    return new PersonBean_MembersInjector(clothesProvider);
  }

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

  public static void injectClothes(PersonBean instance, Provider<Clothes> clothesProvider) {
    instance.clothes = clothesProvider.get();
  }
}

apt插件为PersonBean生成了一个成员注入类,该类提供了PersonBean需要的Clothes实例。PersonBean_Factory也改变成了如下结构:

public final class PersonBean_Factory implements Factory<PersonBean> {
  private final MembersInjector<PersonBean> personBeanMembersInjector;

  private final Provider<String> nameProvider;

  public PersonBean_Factory(
      MembersInjector<PersonBean> personBeanMembersInjector, Provider<String> nameProvider) {
    assert personBeanMembersInjector != null;
    this.personBeanMembersInjector = personBeanMembersInjector;
    assert nameProvider != null;
    this.nameProvider = nameProvider;
  }

  @Override
  public PersonBean get() {
    return MembersInjectors.injectMembers(
        personBeanMembersInjector, new PersonBean(nameProvider.get()));
  }

  public static Factory<PersonBean> create(
      MembersInjector<PersonBean> personBeanMembersInjector, Provider<String> nameProvider) {
    return new PersonBean_Factory(personBeanMembersInjector, nameProvider);
  }
}

2.Component注解

@Component
public interface DemoComponent {

    Student student();
}

apt会为该注解生成一个工厂类:

public final class DaggerDemoComponent implements DemoComponent {
  private DaggerDemoComponent(Builder builder) {
    assert builder != null;
  }

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

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

  @Override
  public Student student() {
    return new Student();
  }

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

    public DemoComponent build() {
      return new DaggerDemoComponent(this);
    }
  }
}

在Component里面添加的抽象方法,会在对应的DaggerDemoComponent类中进行实现。

3.Provider注解和Module注解

@Module
public class OneModule {

    @Provides
    public Clothes provideClothes() {
        return new Clothes("紫色");
    }

    @Provides
    public PersonBean providePersonBean() {
        return new PersonBean("大西瓜");
    }

}

会生成模块名+方法名+Factory的工程类(OneModule_ProvidePersonBeanFactory)。
注意:
1.模块必须要使用Module注解修饰。
2.Module中的方法需要provider开头,否则生成的文件会报错。

public final class OneModule_ProvidePersonBeanFactory implements Factory<PersonBean> {
  private final OneModule module;

  public OneModule_ProvidePersonBeanFactory(OneModule module) {
    assert module != null;
    this.module = module;
  }

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

  public static Factory<PersonBean> create(OneModule module) {
    return new OneModule_ProvidePersonBeanFactory(module);
  }
}

public final class OneModule_ProvideClothesFactory implements Factory<Clothes> {
  private final OneModule module;

  public OneModule_ProvideClothesFactory(OneModule module) {
    assert module != null;
    this.module = module;
  }

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

  public static Factory<Clothes> create(OneModule module) {
    return new OneModule_ProvideClothesFactory(module);
  }
}

4.Singleton注解

@Singleton
@Component(modules = {OneModule.class})
public interface DemoComponent {

    void inject(MainActivity activity);

    Student student();
}

为Component提供Singleton注解,在apt生成的代码中,会进行DoubleCheck的检查,保证单例。

  private void initialize(final Builder builder) {

    this.provideXiguaPersonBeanProvider =
        DoubleCheck.provider(OneModule_ProvideXiguaPersonBeanFactory.create(builder.oneModule));

    this.mainActivityMembersInjector =
        MainActivity_MembersInjector.create(provideXiguaPersonBeanProvider);

    this.studentProvider = DoubleCheck.provider(Student_Factory.create());
  }

二、让组件(Component)依赖Module

@Component(modules = {OneModule.class})
public interface DemoComponent {

    Student student();
}

在DaggerDemoComponent中的Buider对象中生成oneModule(OneModule oneModule)方法。

public final class DaggerDemoComponent implements DemoComponent {
  private DaggerDemoComponent(Builder builder) {
    assert builder != null;
  }

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

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

  @Override
  public Student student() {
    return new Student();
  }

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

    public DemoComponent build() {
      return new DaggerDemoComponent(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 oneModule(OneModule oneModule) {
      Preconditions.checkNotNull(oneModule);
      return this;
    }
  }
}

在Activity中注入对象

public class MainActivity extends AppCompatActivity {

    @Inject
    PersonBean personBean;

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

        DaggerDemoComponent.builder()
                .oneModule(new OneModule())
                .build()
                .inject(this);
    }
}

注意:需要使用inject方法注入指定类。
在加入inject方法后,生成了如下方法。
1.在DaggerDemoComponent中找到所有@Inject修饰的需要注入的变量的provider,并且在build后对这些变量进行赋值。
2.在inject(this)的时候,会将已经赋值的变量找到
MainActivity_MembersInjector(注入类+MembersInjector)中真正的变量进行赋值。

public final class DaggerDemoComponent implements DemoComponent {
  private Provider<PersonBean> providePersonBeanProvider;

  private MembersInjector<MainActivity> mainActivityMembersInjector;

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

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

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

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

    this.providePersonBeanProvider = OneModule_ProvidePersonBeanFactory.create(builder.oneModule);

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

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

  @Override
  public Student student() {
    return new Student();
  }

  public static final class Builder {
    private OneModule oneModule;

    private Builder() {}

    public DemoComponent build() {
      if (oneModule == null) {
        this.oneModule = new OneModule();
      }
      return new DaggerDemoComponent(this);
    }

    public Builder oneModule(OneModule oneModule) {
      this.oneModule = Preconditions.checkNotNull(oneModule);
      return this;
    }
  }
}

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

  public MainActivity_MembersInjector(Provider<PersonBean> personBeanProvider) {
    assert personBeanProvider != null;
    this.personBeanProvider = personBeanProvider;
  }

  public static MembersInjector<MainActivity> create(Provider<PersonBean> personBeanProvider) {
    return new MainActivity_MembersInjector(personBeanProvider);
  }

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

  public static void injectPersonBean(
      MainActivity instance, Provider<PersonBean> personBeanProvider) {
    instance.personBean = personBeanProvider.get();
  }
}

三、其他的一些问题

  1. @Inject 和 @Provides 的优先级
    Dagger2 依赖查找的顺序是先查找 Module 内所有的 @Provides 提供的依赖,如果查找不到再去查找 @Inject 提供的依赖。
上一篇下一篇

猜你喜欢

热点阅读