dagger.android 源码

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方法,也就是最后的赋值操作了。
  • 此时上面的所有流程也就串通了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容