dagger.android 源码

作者: 喂_balabala | 来源:发表于2018-11-05 14:52 被阅读5次

    Demo

    application类

        class BalaApp: Application(),HasActivityInjector {
        
            @Inject
            lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
        
            override fun activityInjector(): AndroidInjector<Activity> {
                return dispatchingAndroidInjector
            }
        
            override fun onCreate() {
                super.onCreate()
        
                DaggerAppComponent.create().inject(this)
            }
        }
    

    AppComponent

        @Component(modules = [AndroidInjectionModule::class, AndroidSupportInjectionModule::class, MainModule::class, SecondModule::class])
        interface AppComponent {
            fun inject(application: BalaApp)
        }
    

    BaseActivity

        open class BaseActivity: AppCompatActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                AndroidInjection.inject(this)
                super.onCreate(savedInstanceState)
            }
        }
    

    MainActivity

        class MainActivity : BaseActivity() {
        
            @Inject
            lateinit var claName:String
            @Inject
            lateinit var student: Student
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
                Log.d("eee=main","-------$claName----------$student")
            }
        
            fun mainClick(view: View){
                when(view.id){
                    R.id.btn_second->startActivity(Intent(this,SecondActivity::class.java))
                }
            }
        }
    

    MainModule

        @Module(subcomponents = [MainSubcomponent::class])
        abstract class MainModule {
        
            @Binds
            @IntoMap
            @ActivityKey(MainActivity::class)
            abstract fun bindMainActivityInjectorFactory(builder: MainSubcomponent.Builder): AndroidInjector.Factory<out Activity>
        
        }
    

    MainSubcomponent

        @Subcomponent(modules = [AndroidInjectionModule::class, MainSubcomponent.SubModule::class])
        interface MainSubcomponent : AndroidInjector<MainActivity> {
        
            @Subcomponent.Builder
            abstract class Builder : AndroidInjector.Builder<MainActivity>() {
        
            }
        
            @Module
            class SubModule {
                @Provides
                fun provideName(): String {
                    return MainActivity::class.java.name
                }
                @Provides
            fun provideStudent():Student{
                    return Student()
                }
            }
        
        }
    

    SecondActivity

        class SecondActivity: BaseActivity() {
        
            @Inject
            lateinit var className:String
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_second)
        
                Log.d("eee=second","-------$className")
            }
        }
    

    SecondComponent

        @Subcomponent(modules = [AndroidInjectionModule::class, SecondComponent.SubModule::class])
        interface SecondComponent : AndroidInjector<SecondActivity> {
            @Subcomponent.Builder
            abstract class Builder : AndroidInjector.Builder<SecondActivity>() {
            }
        
            @Module
            class SubModule {
                @Provides
                fun provideName(): String {
                    return SecondActivity::class.java.name
                }
            }
        
        }
    

    SecondModule

        @Module(subcomponents = [SecondComponent::class])
        abstract class SecondModule {
        
            @Binds
            @IntoMap
            @ActivityKey(SecondActivity::class)
            abstract fun bindSecondActivityInjectorFactory(builder: SecondComponent.Builder): AndroidInjector.Factory<out Activity>
        }
    

    Student

        class Student
    
    module的作用
    • 把对应的Component.Builder跟AndroidInjector.Factory绑定起来。
    • 真正提供数据是在Component中的子module中
    DaggerAppComponent.create做了哪些操作
    • 把每个Subcomponent.Builder封装在Provider中。然后以键值对的方式存储在map集合中
      private void initialize(final Builder builder) {
        this.mainSubcomponentBuilderProvider =
            new Provider<MainSubcomponent.Builder>() {
              @Override
              public MainSubcomponent.Builder get() {
                return new MainSubcomponentBuilder();
              }
            };
        this.secondComponentBuilderProvider =
            new Provider<SecondComponent.Builder>() {
              @Override
              public SecondComponent.Builder get() {
                return new SecondComponentBuilder();
              }
            };
      }
      
        private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
          getMapOfClassOfAndProviderOfFactoryOf() {
        return MapBuilder
            .<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
                newMapBuilder(2)
            .put(MainActivity.class, (Provider) mainSubcomponentBuilderProvider)
            .put(SecondActivity.class, (Provider) secondComponentBuilderProvider)
            .build();
      }
    
    • 在initialize中可以看到,继承匿名Provider内部类,重写了一个get方法。里面new了一个SubcomponentBuilder类,这里就拿到了对应component中子module对象
    • 然后再new一个SubcomponentImpl实现类,里面就进行传统了inject、module、component的操作。
    • 以Main为例,看下MainSubcomponentBuilder的代码
      private final class MainSubcomponentBuilder extends MainSubcomponent.Builder {
        private MainSubcomponent.SubModule subModule;
    
        private MainActivity seedInstance;
    
        @Override
        public MainSubcomponent build() {
          if (subModule == null) {
            this.subModule = new MainSubcomponent.SubModule();
          }
          if (seedInstance == null) {
            throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
          }
          return new MainSubcomponentImpl(this);
        }
    
        @Override
        public void seedInstance(MainActivity arg0) {
          this.seedInstance = Preconditions.checkNotNull(arg0);
        }
      }
    
    • SubcomponentImpl实现类的代码
      private final class MainSubcomponentImpl implements MainSubcomponent {
        private MainSubcomponent.SubModule subModule;
    
        private MainSubcomponentImpl(MainSubcomponentBuilder builder) {
          initialize(builder);
        }
    
        @SuppressWarnings("unchecked")
        private void initialize(final MainSubcomponentBuilder builder) {
          this.subModule = builder.subModule;
        }
    
        @Override
        public void inject(MainActivity arg0) {
          injectMainActivity(arg0);
        }
    
        private MainActivity injectMainActivity(MainActivity instance) {
          MainActivity_MembersInjector.injectClaName(
              instance, MainSubcomponent_SubModule_ProvideNameFactory.proxyProvideName(subModule));
          MainActivity_MembersInjector.injectStudent(
              instance,
              MainSubcomponent_SubModule_ProvideStudentFactory.proxyProvideStudent(subModule));
          return instance;
        }
      }
    
    • 通过上述可以看到,map集合中存储了所有的数据,就看后续是怎么从map集合中拿出来使用了。
    DaggerAppComponent.create().inject(this)做了哪些操作
    • 把上面说的存储了所有数据的map集合再封装到了applic类中的dispatchingAndroidInjector中
      private BalaApp injectBalaApp(BalaApp instance) {
        BalaApp_MembersInjector.injectDispatchingAndroidInjector(
            instance, getDispatchingAndroidInjectorOfActivity());
        return instance;
      }
    
    BaseActivity中的AndroidInjection.inject(this)。以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);
      }
    
    • activityInjector就是application中的dispatchingAndroidInjector,因为DispatchingAndroidInjector是继承AndroidInjector的。所以inject调用的是dispatchingAndroidInjector的inject。看下做了什么操作。
      public boolean maybeInject(T instance) {
        Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
            injectorFactories.get(instance.getClass().getName());
        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);
        }
      }
    
    • 可以看到factoryProvider就是从map集合中拿到了对应的provider,然后调用get方法,就是执行了DaggerAPPComponent的initialize中的匿名内部类的get方法。
    • 以mainActivity为例,get方法就是拿到了MainSubcomponentBuilder对象,然后调用create方法,因为MainSubcomponentBuilder继承MainSubcomponent.Builder,然后MainSubcomponent.Builder又是继承AndroidInjector.Builder。所以这里的create方法调用的是seedInstance
      abstract class Builder<T> implements AndroidInjector.Factory<T> {
        @Override
        public final AndroidInjector<T> create(T instance) {
          seedInstance(instance);
          return build();
        }
    
    • 也就是在MainSubcomponentBuilder重写的seedInstance
        @Override
        public void seedInstance(MainActivity arg0) {
          this.seedInstance = Preconditions.checkNotNull(arg0);
        }
    
    • 然后执行的是maybeInject中的injector.inject(instance);上面可以看到调用seedInstance后返回的是执行build方法后返回的MainSubcomponentImpl对象。
        @Override
        public MainSubcomponent build() {
          if (subModule == null) {
            this.subModule = new MainSubcomponent.SubModule();
          }
          if (seedInstance == null) {
            throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
          }
          return new MainSubcomponentImpl(this);
        }
    
    • 所以这个inject就是执行MainSubcomponentBuilder中重写的inject方法,也就是最后的赋值操作了。
    • 此时上面的所有流程也就串通了

    相关文章

      网友评论

        本文标题:dagger.android 源码

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