美文网首页
Dagger2 Android --- 注解&注入流程分

Dagger2 Android --- 注解&注入流程分

作者: bf027edd3b22 | 来源:发表于2018-10-18 19:17 被阅读141次

    Dagger2 Android --- 注解&注入流程分析篇

    本篇的分析基于前一篇基础使用:

    Dagger2 Android --- 基础使用篇

    注解分析

    上一篇我们知道使用Dagger Android有这几个步骤:

    1. 自定义Application继承DaggerApplication
    2. 创建MainComponent
    3. 创建ActivityBindingModule,SubComponent为MainComponent
    4. 创建AppComponent,modules为AndroidSupportInjectionModule.class,ActivityBindingModule.class
    5. make project,将生成的DaggerAppComponent传给自定义Application
    6. 在MainActivity的onCreate中,使用AndroidInjection.inject(this)实现注入,实现了对象的绑定(也可以让activity继承DaggerActivity,省略这步)

    #自定义Application继承DaggerApplication

    DemoApp代码:

    public class DemoApp extends DaggerApplication {
    
        @Override
        protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
            //需要返回DaggerAppComponent给DaggerApplication
            return DaggerAppComponent.builder().create(this);
            
        }
    }
    

    这一步没有使用任何注解:重点都在DaggerApplication中。那我们就关注下这个类做了什么事情。

    DaggerApplication源码:

    @Beta
    public abstract class DaggerApplication extends Application
        implements HasActivityInjector,
            HasFragmentInjector,
            HasServiceInjector,
            HasBroadcastReceiverInjector,
            HasContentProviderInjector {
    
      @Inject DispatchingAndroidInjector<Activity> activityInjector;
      @Inject DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;
      @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
      @Inject DispatchingAndroidInjector<Service> serviceInjector;
      @Inject DispatchingAndroidInjector<ContentProvider> contentProviderInjector;
      private volatile boolean needToInject = true;
    
      @Override
      public void onCreate() {
        super.onCreate();
        injectIfNecessary();
      }
    
      @ForOverride
      protected abstract AndroidInjector<? extends DaggerApplication> applicationInjector();
    
      private void injectIfNecessary() {
        if (needToInject) {
          synchronized (this) {
            if (needToInject) {
              @SuppressWarnings("unchecked")
              AndroidInjector<DaggerApplication> applicationInjector =
                  (AndroidInjector<DaggerApplication>) applicationInjector();
              applicationInjector.inject(this);
              if (needToInject) {
                throw new IllegalStateException(
                    "The AndroidInjector returned from applicationInjector() did not inject the "
                        + "DaggerApplication");
              }
            }
          }
        }
      }
    
      @Inject
      void setInjected() {
        needToInject = false;
      }
    
      @Override
      public DispatchingAndroidInjector<Activity> activityInjector() {
        return activityInjector;
      }
    
      ...
    }
    

    源码主要做了两件事:

    • 提供四大组件及Fragment的注解分发器:DispatchingAndroidInjector<T>
    • 在onCreate时,且需要注入时,调用applicationInjector.inject(this);实现注入

    那applicationInjector是什么时候创建的呢?

    @ForOverride
    protected abstract AndroidInjector<? extends DaggerApplication> applicationInjector();
    

    在我们继承DaggerApplication会默认实现该方法,并且将实现了AndroidInjector<DemoApp>接口的类返回给父类。

    那实现了AndroidInjector<DemoApp>接口的类 又是什么时候生成的呢?

    这个问题先放一放,稍后分析,我们看第二步

    MainComponent

    模板代码,泛型为需要注入的类:

    @Subcomponent
    public interface MainComponent extends AndroidInjector<MainActivity> {
    
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<MainActivity>{}
    
    }
    

    这边用到了两个注解:

    1. SubComponent

      使用SubComponet是为了继承父类的依赖图,父类中使用注解提供依赖的对象,在MainComponent中,同样可以使用。

      同时会生成XXXComponentImpl的final类

       private final class MainComponentImpl implements MainComponent {
         private MainComponentImpl(MainComponentBuilder builder) {}
      
         @Override
         public void inject(MainActivity arg0) {
           injectMainActivity(arg0);
         }
      
         private MainActivity injectMainActivity(MainActivity instance) {
           DaggerAppCompatActivity_MembersInjector.injectSupportFragmentInjector(
               instance, DaggerAppComponent.this.getDispatchingAndroidInjectorOfFragment2());
           DaggerAppCompatActivity_MembersInjector.injectFrameworkFragmentInjector(
               instance, DaggerAppComponent.this.getDispatchingAndroidInjectorOfFragment());
           MainActivity_MembersInjector.injectStudent(instance, new Student());
           return instance;
         }
       }
      

      该类中,会通过inject方法将MainActivityStudent对象进行绑定,将Student注入到MainActivity中。

      我们还可以看到,除了注入了Student之外,还注入了Fragment和SupportFragment。

    2. SubComponent.Builder

      使用了该注解,会生成XXXComponentBuilder的final类,

      private final class MainComponentBuilder extends MainComponent.Builder {
        private MainActivity seedInstance;
      
        @Override
        public MainComponent build() {
          if (seedInstance == null) {
            throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
          }
          return new MainComponentImpl(this);
        }
      
        @Override
        public void seedInstance(MainActivity arg0) {
          this.seedInstance = Preconditions.checkNotNull(arg0);
        }
      }
      

      这个类比较重要,其中持有了MainActivity实例。

      通过seedInstance传入MainActivity,同时通过build创建MainComponentImpl,这样MainComponentImpl也就拥有了MainActivity实例。

      那么seedInstance又是在什么地方调用的呢?

    3. AndroidInjector<T>

      MainComponentImpl实现了MainComponentMainComponentBuilder又继承了抽象类MainComponent.Builder

      是不是有点眼熟,对!就是我们刚才创建的MainComponent。MainComponent又继承了AndroidInjector接口。

      我们再看下MainComponent代码:

       @Subcomponent
       public interface MainComponent extends AndroidInjector<MainActivity> {
       
           @Subcomponent.Builder
           abstract class Builder extends AndroidInjector.Builder<MainActivity>{}
       
       }
      

      所以先看AndroidInjector源码:

       @Beta
       public interface AndroidInjector<T> {
       
         void inject(T instance);
       
         interface Factory<T> {
         
           AndroidInjector<T> create(T instance);
         }
       
         abstract class Builder<T> implements AndroidInjector.Factory<T> {
           @Override
           public final AndroidInjector<T> create(T instance) {
             seedInstance(instance);
             return build();
           }
       
           @BindsInstance
           public abstract void seedInstance(T instance);
       
           public abstract AndroidInjector<T> build();
         }
       }
      

      定义了一个inject方法实现注入;一个工厂类,用来创建该对象。这里就是Dagger2 Android的核心了:面向接口编程,移除被注入者对注入者的依赖

      这里通过调用create传入需要的目标对象,并通过seedInstance设置,然后再调用build方法。

      因为 MainComponentBuilder 继承了 Factory,所有也就是调用其内部的build方法,build做了什么事?? --> 可以翻到上面看看

      这边用到一个比较重要的注解: @BindsInstance

      添加了该注解的方法,会默认在子类里面生成一个 T类型的对象,同时在 seedInstance 方法里面进行复制

       private final class MainComponentBuilder extends MainComponent.Builder {
         private MainActivity seedInstance;
         ...
      
         @Override
         public void seedInstance(MainActivity arg0) {
           this.seedInstance = Preconditions.checkNotNull(arg0);
         }
       }
      

      这两块代码就是通过该注解实现的。现在再来通过这张图梳理一下:

    image

    创建ActivityBindingModule

    还是先看下代码:

    @Module(subcomponents = {MainComponent.class})
    public abstract class ActivityBindingModule {
    
        @Binds
        @IntoMap
        @ActivityKey(MainActivity.class)
        abstract AndroidInjector.Factory<? extends Activity> bindMainActivityInjectorFactory(MainComponent.Builder builder);
        
    }
    

    这边用到了5个注解:

    • Module,subcomponents:这两个应该都知道了
    • Binds:比较重要的一个注解,告诉dagger,参数是实现了AndroidInjector.Factory接口的类,生成代码的时候会去遍历添加了Inject注解的类,查看是否实现了该接口,然后动态生成;当然也可以通过@Providers和new实现
    • IntoMap,ActivityKey:这两个是配对使用的,意思就是将生成的MainComponent.Builder对象放入到Map中,key为ActivityKey(除了ActivityKey,还有StringKey、booleanKey等等)

    这一步的作用就是统一管理注入 Builder 类。

    下面我们看下生成的代码,验证下刚才的分析:

    public final class DaggerAppComponent implements AppComponent {
      private Provider<MainComponent.Builder> mainComponentBuilderProvider;
    
        ... 
      
        private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
            getMapOfClassOfAndProviderOfFactoryOf() {
          return Collections
              .<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
                  singletonMap(MainActivity.class, (Provider) mainComponentBuilderProvider);
        }
      
       ...
     }
    

    确实如此:

    使用Binds最终也是通过Provider提供的对象,然后再存入MapBuilder中,等待后续使用。

    AppComponent类

    AppComponent类:

    @Component(modules = {
            AndroidSupportInjectionModule.class,
            ActivityBindingModule.class
    })
    public interface AppComponent extends AndroidInjector<DemoApp> {
    
        @Component.Builder
        abstract class Builder extends AndroidInjector.Builder<DemoApp> {
    
        }
    }
    

    这边有个AndroidSupportInjectionModule,继承自AndroidInjectionModule,这个是干嘛用的呢?

    AndroidInjectionModule源码:

    @Beta
    @Module
    public abstract class AndroidInjectionModule {
      @Multibinds
      abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>>
          activityInjectorFactories();
    
      @Multibinds
      abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>>
          fragmentInjectorFactories();
    
      @Multibinds
      abstract Map<Class<? extends Service>, AndroidInjector.Factory<? extends Service>>
          serviceInjectorFactories();
    
      @Multibinds
      abstract Map<
              Class<? extends BroadcastReceiver>, AndroidInjector.Factory<? extends BroadcastReceiver>>
          broadcastReceiverInjectorFactories();
    
      @Multibinds
      abstract Map<
              Class<? extends ContentProvider>, AndroidInjector.Factory<? extends ContentProvider>>
          contentProviderInjectorFactories();
    
      private AndroidInjectionModule() {}
    }
    

    又有点熟悉了,和我们刚才分析的ActivityBindingModule有点类似。

    这个module的作用:

    1. 通过ActivityBindingModule生成并保存了所有的AcitivtyBuilder到Map中
    2. 然后通过这个module将Map提供给AppComponent

    再来看下生成的DaggerAppComponent:

    public final class DaggerAppComponent implements AppComponent {
      private Provider<MainComponent.Builder> mainComponentBuilderProvider;
    
      private DaggerAppComponent(Builder builder) {
        initialize(builder);
      }
    
      public static AppComponent.Builder builder() {
        return new Builder();
      }
    
        private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
            getMapOfClassOfAndProviderOfFactoryOf() {
          return Collections
              .<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
                  singletonMap(MainActivity.class, (Provider) mainComponentBuilderProvider);
        }
    
      private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
        return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
            getMapOfClassOfAndProviderOfFactoryOf());
      }
    
      ...
      
      private DispatchingAndroidInjector<android.support.v4.app.Fragment>
          getDispatchingAndroidInjectorOfFragment2() {
        return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
            Collections
                .<Class<? extends android.support.v4.app.Fragment>,
                    Provider<AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>>
                    emptyMap());
      }
    
      @SuppressWarnings("unchecked")
      private void initialize(final Builder builder) {
        this.mainComponentBuilderProvider =
            new Provider<MainComponent.Builder>() {
              @Override
              public MainComponent.Builder get() {
                return new MainComponentBuilder();
              }
            };
      }
    
      @Override
      public void inject(DemoApp arg0) {
        injectDemoApp(arg0);
      }
    
      private DemoApp injectDemoApp(DemoApp instance) {
        DaggerApplication_MembersInjector.injectActivityInjector(
            instance, getDispatchingAndroidInjectorOfActivity());
        ...
        return instance;
      }
    
      private static final class Builder extends AppComponent.Builder {
        private DemoApp seedInstance;
    
        @Override
        public AppComponent build() {
          if (seedInstance == null) {
            throw new IllegalStateException(DemoApp.class.getCanonicalName() + " must be set");
          }
          return new DaggerAppComponent(this);
        }
    
        @Override
        public void seedInstance(DemoApp arg0) {
          this.seedInstance = Preconditions.checkNotNull(arg0);
        }
      }
    
      private final class MainComponentBuilder extends MainComponent.Builder {
        ...
      }
    
      private final class MainComponentImpl implements MainComponent {
        ...
      }
    }
    

    代码有点多,所有我们就从入口开始看:

    DaggerAppComponent.builder().create(this);
    

    builder().create(),还记得上面的图吗,注入模板类就是通过这个调用生成的。

    一步一步看create的执行流程,可以看到两行关键代码:

    • new DaggerAppComponent(this);
    • new MainComponentBuilder();

    到这边,所有的依赖图谱都已经构建完成。

    注入的最终实现 inject

    1. 注入到DemoApp
    AndroidInjector<DemoApp> 中inject方法的调用

    @Beta
    public abstract class DaggerApplication extends Application
        implements HasActivityInjector,
            HasFragmentInjector,
            HasServiceInjector,
            HasBroadcastReceiverInjector,
            HasContentProviderInjector {
    
      ...
    
      @Override
      public void onCreate() {
        super.onCreate();
        injectIfNecessary();
      }
    
      @ForOverride
      protected abstract AndroidInjector<? extends DaggerApplication> applicationInjector();
    
      private void injectIfNecessary() {
        if (needToInject) {
          synchronized (this) {
            if (needToInject) {
              @SuppressWarnings("unchecked")
              AndroidInjector<DaggerApplication> applicationInjector =
                  (AndroidInjector<DaggerApplication>) applicationInjector();
              applicationInjector.inject(this);
              if (needToInject) {
                throw new IllegalStateException(
                    "The AndroidInjector returned from applicationInjector() did not inject the "
                        + "DaggerApplication");
              }
            }
          }
        }
      }
    }
    

    applicationInjector对象的生成:

    public class DemoApp extends DaggerApplication {
    
        @Override
        protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
            return DaggerAppComponent.builder().create(this);
        }
    }
    

    还记得之前的疑问吗,AndroidInjector<DemoApp> 对象就是在这里创建的。

    在DaggerApplication内部可以看到,如果需要注入,就会执行applicationInjector.inject(this)方法;而DaggerAppComponent正式实现了AndroidInjector的类,却在create的时候已经创建。

    2. 注入到MainActivity

    调用AndroidInjection.inject(this);

    public class MainActivity extends DaggerAppCompatActivity {
    
        @Inject
        Student student;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            AndroidInjection.inject(this);
            setContentView(R.layout.activity_main);
        }
    }
    

    AndroidInjection:

    @Beta
    public final class AndroidInjection {
      ...
    
      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);
      }
    }
    

    最终也是通过AndroidInjector<Activity> 的 inject 方法实现注入,

    同样在create的时候,已经创建了MainComponentBuilderMainComponentBuilder内部又会创建MainComponentImpl,而MainComponentImpl正是实现了AndroidInjector<Activity>的类。

    所有这里的activityInjector对象肯定是存在的,整个注入流程也就实现了。

    流程梳理

    可以看出,Dagger Android实现自动注入主要分为两部分:

    1. 注入代码的生成、依赖图谱的构建

       @Beta
       public interface AndroidInjector<T> {
       
         ...
         
         abstract class Builder<T> implements AndroidInjector.Factory<T> {
           @Override
           public final AndroidInjector<T> create(T instance) {
             seedInstance(instance);
             return build();
           }
       
           @BindsInstance
           public abstract void seedInstance(T instance);
       
           public abstract AndroidInjector<T> build();
         }
      

      }

      通过抽象类约束生成Dagger注入模板代码,在Application中调用create的时候,会解析依赖图谱并生成所有的注入模板代码

    1. 注入的实现

       @Beta
       public interface AndroidInjector<T> {
       
         void inject(T instance);
       
         interface Factory<T> {
           AndroidInjector<T> create(T instance);
         }
       
         abstract class Builder<T> implements AndroidInjector.Factory<T> {
           @Override
           public final AndroidInjector<T> create(T instance) {
             seedInstance(instance);
             return build();
           }
       
           @BindsInstance
           public abstract void seedInstance(T instance);
       
           public abstract AndroidInjector<T> build();
         }
       }
      

      通过调用inject传入需要使用的对象。

    新注解使用

    Dagger Android虽然说实现了解耦,但是步骤实在太繁琐了。

    所以在2.11之后,有了@ContributesAndroidInjector注解

    新建了一个Module类,声明需要被注入的Activity:

    @Module
    public abstract class NewActivityBindingModule {
    
        @ContributesAndroidInjector(modules = MainModule.class)
        abstract MainActivity mainActivity();
    
        @ContributesAndroidInjector
        abstract DetailActivity detailActivity();
    }
    

    替换AppComponent里面的modules:

    @Component(modules = {
            AndroidSupportInjectionModule.class,
            NewActivityBindingModule.class,
    //        ActivityBindingModule.class
    })
    public interface AppComponent extends AndroidInjector<DemoApp> {
    
        @Component.Builder
        abstract class Builder extends AndroidInjector.Builder<DemoApp> {
    
        }
    }
    

    对! 就这么简单,没有了MainComponent,没有了@Binds...,一个注解就帮我们做到了。

    make project:

    生成了两个ActivityBinding_Module类:

    image

    这个类里面又帮我们把重复工作做掉了,尽可能减少使用者的麻烦

    @Module(subcomponents = NewActivityBindingModule_DetailActivity.DetailActivitySubcomponent.class)
    public abstract class NewActivityBindingModule_DetailActivity {
      private NewActivityBindingModule_DetailActivity() {}
    
      @Binds
      @IntoMap
      @ActivityKey(DetailActivity.class)
      abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory(
          DetailActivitySubcomponent.Builder builder);
    
      @Subcomponent
      public interface DetailActivitySubcomponent extends AndroidInjector<DetailActivity> {
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<DetailActivity> {}
      }
    }
    

    相关文章

      网友评论

          本文标题:Dagger2 Android --- 注解&注入流程分

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