AAC学习笔记Dagger(三)

本文为《Android Architecture Components学习笔记》的一部分
文档代码为Kotlin,但是系统生成的代码仍然为Java
为了方便理解,我将官方示例做了逐步拆解
本人水平有限,如有不当之处请不吝赐教


上一篇叨叨到了将DispatchingAndroidInjector对象注入到ApplicationDispatchingAndroidInjector对象里有个Map,K是Class,前面的代码可以看到V最终是mainActivitySubcomponentBuilderProvider

this.mainActivitySubcomponentBuilderProvider =
        new Provider<MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder>() {
          @Override
          public MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder get() {
            return new MainActivitySubcomponentBuilder();
          }
        };

上一篇仅仅到此而已。那么Activity也没注入啊,还有Activity注入到底有什么意义呢?带着这两个问题,继续看吧。


AppInjector(二)

如果实际项目将Activity作为一个模块入口来看,那这个模块可能要包含Fragment、ViewModel、Repository……为了项目达到解耦的效果,应用注入的理念是个很好的选择。所以,Activity注入其实最终效果要达到与之相关的东西都能注入,因为起始于Application是最初的入口。

再回到前面看AppInjector.init第二句:

githubApp.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
                //重写onActivityCreated,以实现Activity注入
                override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { 
                        handleActivity(activity)
                }
            })
    }

    private fun handleActivity(activity: Activity) {
        //要注入Activity就需要实现HasSupportFragmentInjector
        if (activity is HasSupportFragmentInjector) {
            AndroidInjection.inject(activity)
        }
       if (activity is FragmentActivity) {
            activity.supportFragmentManager
                .registerFragmentLifecycleCallbacks(
                    object : FragmentManager.FragmentLifecycleCallbacks() {
                        //重写onFragmentCreated以实现Fragment注入
                        override fun onFragmentCreated(
                            fm: FragmentManager,
                            f: Fragment,
                            savedInstanceState: Bundle?
                        ) {
                            //Fragment必须实现Injectable(这是个空接口,仅仅作为标志区分是否需要注入而已)
                            if (f is Injectable) {
                                AndroidSupportInjection.inject(f)
                            }
                        }
                    }, true
                )
        }

没啥好说的,贴上示例里最终MainActivity的代码:

//实现了HasSupportFragmentInjector 接口
class MainActivity : AppCompatActivity(), HasSupportFragmentInjector {
    //注入DispatchingAndroidInjector<Fragment>以准备此Activity所属Fragment的注入
    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
    }

    override fun supportFragmentInjector() = dispatchingAndroidInjector
}

这里需要往MainActivity里注入DispatchingAndroidInjector注意这里包含的是Fragment
既然注入就必须要Module:

//为了方便分析,这里三个Fragment暂时都是空的
@Suppress("unused")
@Module
abstract class FragmentBuildersModule {
    @ContributesAndroidInjector
    abstract fun contributeRepoFragment(): RepoFragment

    @ContributesAndroidInjector
    abstract fun contributeUserFragment(): UserFragment

    @ContributesAndroidInjector
    abstract fun contributeSearchFragment(): SearchFragment
}

这个Module要加到MainActivityModule里:

@Suppress("unused")
@Module
abstract class MainActivityModule {
    //在这里噢
    @ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
    abstract fun contributeMainActivity(): MainActivity
}

Ok,Build。然后就是看着DaggerAppComponent分析实现方法了。

Activity注入过程

1、先看看AppInjector.handleActivity里这句AndroidInjection.inject(activity)

  public static void inject(Activity activity) {
    checkNotNull(activity, "activity");
    Application application = activity.getApplication();
    if (!(application instanceof HasActivityInjector)) {throw new RuntimeException(...);}
    //得到activityInjector,这里得到的是GithubApp里的,也就是包含Activity的dispatchingAndroidInjector
    AndroidInjector<Activity> activityInjector =
        ((HasActivityInjector) application).activityInjector();
    //执行DispatchingAndroidInjector.inject,并传入MainActivity
    activityInjector.inject(activity);
  }

2、进入DispatchingAndroidInjector

  public void inject(T instance) {
    boolean wasInjected = maybeInject(instance);
  }

  public boolean maybeInject(T instance) {
    //得到Map里K为MainActivity的Builder
    Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
        injectorFactories.get(instance.getClass());
    if (factoryProvider == null) {
      return false;
    }
    //此处执行的get()为DaggerAppComponent.initialize里重写的
    //根据传过来的instance,执行return new ***SubcomponentBuilder();
    AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
    /*
    *此处create()执行的是接口AndroidInjector内部类Builder.create(),这是java8新特性
    *首先运行:DaggerAppComponent.**SubcomponentBuilder.seedInstance(MainActivity arg0)
    *然后返回:MainActivityModule_ContributeMainActivity.MainActivitySubcomponent build()
    *build()里return new **SubcomponentImpl(this);
    */
    AndroidInjector<T> injector =checkNotNull(factory.create(instance),,);
    //执行的为**SubcomponentImpl.inject
    injector.inject(instance);
    return true;
  }

可以看出,这里开启了**SubcomponentImpl的inject,看看都做了什么
DaggerAppComponent.MainActivitySubcomponentImpl

private final class MainActivitySubcomponentImpl
      implements MainActivityModule_ContributeMainActivity.MainActivitySubcomponent {
    //MainActivity的三个Fragment
    private Provider<~.RepoFragmentSubcomponent.Builder>repoFragmentSubcomponentBuilderProvider;
    private Provider<~.UserFragmentSubcomponent.Builder>userFragmentSubcomponentBuilderProvider;
    private Provider<~.SearchFragmentSubcomponent.Builder>searchFragmentSubcomponentBuilderProvider;

    private MainActivitySubcomponentImpl(MainActivitySubcomponentBuilder builder) {initialize(builder);}
    private void initialize(final MainActivitySubcomponentBuilder builder) {
      this.repoFragmentSubcomponentBuilderProvider =
          new Provider<
              FragmentBuildersModule_ContributeRepoFragment.RepoFragmentSubcomponent.Builder>() {
            @Override
            public FragmentBuildersModule_ContributeRepoFragment.RepoFragmentSubcomponent.Builder
                get() {
              return new RepoFragmentSubcomponentBuilder();
            }
          };
    //一共三套,就略了……
    }
    private Map<Class<? extends Fragment>, Provider<AndroidInjector.Factory<? extends Fragment>>>
        getMapOfClassOfAndProviderOfFactoryOf() {
      return MapBuilder
          .<Class<? extends Fragment>, Provider<AndroidInjector.Factory<? extends Fragment>>>
              newMapBuilder(3)
          .put(RepoFragment.class, (Provider) repoFragmentSubcomponentBuilderProvider)
          .put(UserFragment.class, (Provider) userFragmentSubcomponentBuilderProvider)
          .put(SearchFragment.class, (Provider) searchFragmentSubcomponentBuilderProvider)
          .build();
    }

    private DispatchingAndroidInjector<Fragment> getDispatchingAndroidInjectorOfFragment() {
      //这里new了DispatchingAndroidInjector
      return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
          getMapOfClassOfAndProviderOfFactoryOf());
    }
……

与之前看Activity的模式一样,new了一个DispatchingAndroidInjector放到Maintivity里,这里Map包含的都是与Maintivity有关的Fragment

总结一下

  • Activity、Fragment的注入都依赖DispatchingAndroidInjector
  • DispatchingAndroidInjector里的Map保存了Module里定义的Activity、Fragment
  • 通过重写onActivityCreated()让它们加载的时候通过Builder实现注入

猜你喜欢

转载自blog.csdn.net/jouter/article/details/83374002