Dagger2 系列(四)Dagger2.Android基本原理

前言

上篇文章我们介绍了dagger2.android的如何使用,知其然知其所以然,本篇我们一起来看下,dagger2.android是怎么在dagger2基础上实现注入的。

注意

  • 本篇不讲代码生成过程,后续文章介绍。
  • 本篇讲解dagger2.android注入原理肯定还是dagger2注入原理,所以请先阅读前3篇文章,了解Provider、Builder 、SubcomponentImpl、MembersInjector等主要类作用。

dagger2和dagger2.android 调用注入的区别

调用区别我们上篇文章已经详细讲到,本篇从调用区别引入原理实现。dagger2中acitivity实现注入代码如下:

private void initInjector() {
      mComponent = getAppComponent()
          .mainActivityComponent()
          .activity(this)
          .build();
}

dagger2.anodriod中acitivity实现注入代码如下:
Application的改造代码:

public class MyApplication extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerMyAppComponent.create().inject(this);
    }
    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

activity的注入代码

@Override
protected void onCreate(@Nullable Bundle  savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
}

区别为:
dagger2.android的调要先改造了Application,activity里不需要再调用具体的component接口方法。
代码虽有区别,完成任务是一样的。完成:
拿到MainActivityComponent的的实现类,然后实现MainActivity的注入。
我们本篇就是要讲解dagger2.android是怎么完成这个过程的,从代码上看就是,DaggerMyAppComponent.create().inject(this)和 AndroidInjection.inject(this)做了什么。还是以MainActivity注入为例。

dagger2.android 注入原理

DaggerMyAppComponent.create().inject(this)

先给出这行代码作用的结论:

将MainActivityComponent等subComponent的实现类的工厂实例缓存(简单理解方式,实际缓存是工厂实例进一步封装)起来,activity注入时候备用。

两个问题:

  • 缓存在哪?
    缓存在Application的dispatchingAndroidInjector中。
  • 如何缓存?
    也是通过注入方式缓存。
    带着结论我们开始撸代码,DaggerMyAppComponent.create()方法:
 public static MyAppComponent create() {
    return new Builder().build();
  }
public static final class Builder {
    private Builder() {}

    public MyAppComponent build() {
      return new DaggerMyAppComponent(this);
    }
  }

就是返回了DaggerMyAppComponent实例。DaggerMyAppComponent初始化又做了什么:

 private DaggerMyAppComponent(Builder builder) {
    initialize(builder);
  }
 private void initialize(final Builder builder) {
    this.mainActivitySubcomponentBuilderProvider =
        new Provider<
            AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder>() {
          @Override
          public AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder
           //待会要回调此处,请注意  
            get() {
            return new MainActivitySubcomponentBuilder();
          }
        };
    this.secondActivitySubcomponentBuilderProvider =
......
  }

实例化了mainActivitySubcomponentBuilderProvider 、secondActivitySubcomponentBuilderProvider 等SubcomponentBuilderProvider ,这里Provider细节不再深入,简单理解为Subcomponent实现类的工厂类。这里完成了Subcomponent实现类的工厂类的实例化,接下来就是把他缓存起来了。
inject()方法源码:

@Override
public void inject(MyApplication application) {
    injectMyApplication(application);
}

private MyApplication injectMyApplication(MyApplication instance) {
    MyApplication_MembersInjector.injectDispatchingAndroidInjector(
        instance, getDispatchingAndroidInjectorOfActivity());
    return instance;
  }
}

代码调用到了MyApplication_MembersInjector的injectDispatchingAndroidInjector方法,第二个参数getDispatchingAndroidInjectorOfActivity()方法返回的是对上面我初始化的Provider进一步封装后的结果。在dagger2中MembersInjector是真正完成注入的地方,我们看进去为MyApplication注入了什么。

public static void injectDispatchingAndroidInjector(
      MyApplication instance, DispatchingAndroidInjector<Activity> dispatchingAndroidInjector) {
    instance.dispatchingAndroidInjector = dispatchingAndroidInjector;
}

到这里,真正的我们之前说的:用注入的方式把subComponent的实现类的工厂实例缓存在Application的dispatchingAndroidInjector中。

AndroidInjection.inject(this)

这行代码完成的工作是:

从Application的dispatchingAndroidInjector中获取MainActivityComponent的的实现类实例,然后完成MainActivity的注入。

public static void inject(Activity activity) {
    checkNotNull(activity, "activity");
    Application application = activity.getApplication();
    if (!(application instanceof HasActivityInjector)) {
      throw new RuntimeException(
          String.format(
              "%s does not implement %s",
              application.getClass().getCanonicalName(),
                   HasActivityInjector.class.getCanonicalName()));
    }

AndroidInjector<Activity> activityInjector =
        ((HasActivityInjector) application).activityInjector();
    checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());

 activityInjector.inject(activity);
  }

代码解释:异常处理,然后得到application的dispatchingAndroidInjector,调用其inject(activity)方法。
继续看到DispatchingAndroidInjector中inject方法:

  @Override
  public void inject(T instance) {
    boolean wasInjected = maybeInject(instance);
    if (!wasInjected) {
      throw new IllegalArgumentException(errorMessageSuggestions(instance));
    }
  }
public boolean maybeInject(T instance) {
    Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
        injectorFactories.get(instance.getClass());
    if (factoryProvider == null) {
      return false;
    }

    @SuppressWarnings("unchecked")
    AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
    try {
      AndroidInjector<T> injector =
          checkNotNull(
              factory.create(instance), "%s.create(I) should not return null.", factory.getClass());

      injector.inject(instance);
      return true;
    } catch (ClassCastException e) {
      throw new InvalidInjectorBindingException(
          String.format(
              "%s does not implement AndroidInjector.Factory<%s>",
              factory.getClass().getCanonicalName(), instance.getClass().getCanonicalName()),
          e);
    }
  }

代码又调用到maybeInject方法,还是以MainActivity为例,

  • 获得MainActivity对应我们之前缓存的Provider
  • 调用get方法获得MainActivitySubcomponentBuilder实例factory(参考上面provider实例化的地方get的具体实现)
  • 调用MainActivitySubcomponentBuilder的create方法,create方法中又调用到build方法:
@Override
public AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent build() {
      if (seedInstance == null) {
        throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
      }
      return new MainActivitySubcomponentImpl(this);
    }
}

最终我终于得到了MainActivitySubcomponent的实现类MainActivitySubcomponentImpl,回到上面主流程中,调用了其inject方法:

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

private MainActivity injectMainActivity(MainActivity instance) {
      MainActivity_MembersInjector.injectClassName(
          instance, MainActivityModule_ProvideNameFactory.proxyProvideName());
      MainActivity_MembersInjector.injectSp(instance, getSharedPreferences());
      MainActivity_MembersInjector.injectPresenter(instance, getMainPresenter());
      MainActivity_MembersInjector.injectS1(instance, provideStudentProvider.get());
      MainActivity_MembersInjector.injectS2(instance, provideStudentProvider.get());
      return instance;
    }
}

到这里终于调用了各种MembersInjector完成了MainActivity的注入。
最后一句话总结dagger2.android的注入原理:

将MainActivityComponent的实现类的工厂实例(简单理解)缓存起来,MainActivity注入时取出工厂实例,build构建得到MainActivitySubcomponentImpl后,完成MainActivity注入。