美文网首页Android-Dagger2Android-Rxjava&retrofit&dagger
Dagger2 系列(四)Dagger2.Android基本原理

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

作者: 嘎啦果安卓兽 | 来源:发表于2018-06-27 10:47 被阅读53次

    前言

    上篇文章我们介绍了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注入。

    相关文章

      网友评论

        本文标题:Dagger2 系列(四)Dagger2.Android基本原理

        本文链接:https://www.haomeiwen.com/subject/rehbyftx.html