从生成代码来学习Dagger2的注入过程

前言

用过的同学都会知道,Dagger2用于去除依赖,通过注解便可以为我们生成创建对象的代码。通过apt插件在编译阶段生成注入代码,反射只在编译阶段使用,在应用运行阶段没有涉及到注解反射。下面直接进入生成代码的分析,这也是我最近对生成代码学习的记录。

当我们使用Dagger编写好代码后,build一下,只要依赖关系没问题,那么就可以在app/build/generated/source/kapt(用kotlin)目录下的debug中看到生成的代码。

MainPresenter_Factory

这是添加@Inject注解的代码

class MainPresenter @Inject constructor(val mainView: IMainView, val mainModel: IModel)

对应生成的代码为:

public final class MainPresenter_Factory implements Factory<MainPresenter> {
  private final Provider<IMainView> mainViewProvider;

  private final Provider<IModel> mainModelProvider;

  public MainPresenter_Factory(
      Provider<IMainView> mainViewProvider, Provider<IModel> mainModelProvider) {
    this.mainViewProvider = mainViewProvider;
    this.mainModelProvider = mainModelProvider;
  }

  @Override
  public MainPresenter get() {
    return new MainPresenter(mainViewProvider.get(), mainModelProvider.get());
  }

  public static MainPresenter_Factory create(
      Provider<IMainView> mainViewProvider, Provider<IModel> mainModelProvider) {
    return new MainPresenter_Factory(mainViewProvider, mainModelProvider);
  }
}
  • 构造方法:很明显跟我们写的那个类的构造方法很相似,只是这里的类型是Provider并把类型参数指定跟我们原始一样。
  • get()方法:创建一个我们想要的实例并返回。
  • create()方法:是一个静态方法,创建此类的实例

这里的Provider又是从哪里来的呢?还有它是怎么样的?

//它是一个接口并提供一个get方法
public interface Provider<T> {
    T get();
}

接下来看看生成的Factory类:

MainModule_ProvidesMainModelFactory

public final class MainModule_ProvidesMainModelFactory implements Factory<IModel> {
  private final MainModule module;

  public MainModule_ProvidesMainModelFactory(MainModule module) {
    this.module = module;
  }

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

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

  public static IModel proxyProvidesMainModel(MainModule instance) {
    return Preconditions.checkNotNull(
        instance.providesMainModel(), "Cannot return null from a non-@Nullable @Provides method");
  }
}

  • 构造函数:传入MainModule,也就是我们写的Module类
  • get方法:获取IModel类
  • create方法:传入MainModule并创建此类的实例

这个类继承于Factory,而Factory又继承于Provider,这里便可以回答上面的Provider是这个类的实例,MainView的结构也是跟此类一致的。

注入

				 DaggerAppComponent
                .builder()
                .mainModule(MainModule(this))
                .build()
                .inject(this)

DaggerAppComponent中的Builder

Builder实际的作用就是将外界传进来的实例等存起来,然后通过build方法创建DaggeAppComponent对象,并将自己传送给DaggerAppComponent对象。

public AppComponent build() {
      if (mainModule == null) {
        throw new IllegalStateException(MainModule.class.getCanonicalName() + " must be set");
      }
      return new DaggerAppComponent(this);
    }
//保存MainModule
    public Builder mainModule(MainModule mainModule) {
      this.mainModule = Preconditions.checkNotNull(mainModule);
      return this;
    }

DaggerAppComponent的构造函数

private DaggerAppComponent(Builder builder) {
    initialize(builder);
  }
//将builder中的数据用来初始化
private void initialize(final Builder builder) {
    this.mainModule = builder.mainModule;
  }

inject()方法

  @Override
  public void inject(MainActivity activity) {
    injectMainActivity(activity);
  }

private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectMPresenter(instance, getMainPresenter());
    return instance;
  }

#MainActivity_MembersInjector
public static void injectMPresenter(MainActivity instance, IPresenter mPresenter) {
    instance.mPresenter = mPresenter;
  }

到这,便可以看到presenter的赋值动作,也就是生成的代码为我们创建对象,并进行赋值,真的太秀了。

总结

  • 从Module查找,找不到则查找@Inject标注的构造函数
  • 通过xxx_MemberInjector.injectXXX(目标对象)实现注入
  • @Provider标注的话,都会通过Provider的get提供(里边调用的是module对应的provider方法)
  • @Inject标注的构造方法,会生成对应的Factory,提供get方法获取对应的实例,里边进行了new操作

Demo链接

你可能感兴趣的:(Android)