本文为《Android Architecture Components学习笔记》的一部分
文档代码为Kotlin,但是系统生成的代码仍然为Java
为了方便理解,我将官方示例做了逐步拆解
本人水平有限,如有不当之处请不吝赐教
上一篇叨叨到了将DispatchingAndroidInjector
对象注入到Application
。DispatchingAndroidInjector
对象里有个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实现注入