系列文章
上一篇文章的末尾,提到了ApplicationModel_Factory这个类,当时在Application实现依赖注入的时候并没有用到生成的这个类,就没有继续介绍了,这篇我们就来了解下。
在Activity中实现依赖注入
因为在Application中依赖注入不会用到这个ApplicationModel_Factory,所以看下在Activity中实现依赖注入会不会用到ApplicationModel_Factory,为了更贴近语义,将ApplicationModel修改为ActivityModel,然后注入到Activity中,代码如下
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var model: ActivityModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
model.doSomething()
}
}
编译运行下,打印的日志如下
再看下编译后生成的文件,如下
可以看到这里新生成了两个文件,Hilt也是通过这两个文件实现Activity中的依赖注入的,下面通过这两个文件来了解下Hilt在Activity实现依赖注入的原理。
Hilt_MainActivity分析
通过前面两篇的内容可以知道,MainActivity编译后会继承至Hilt_MainActivity,看下Hilt_MainActivity代码
从上面的截图中可以看到,通过Hilt_MainActivity的构造方法会注册一个监听,当这个类与Context关联时会收到回调,然后继续调用inject方法,inject方法的代码如下
因为inject方法调用的方法会较多,这里就画出调用的时序图,重要的地方再讲下代码,部分时序图如下
这里看下时序图上的getViewModelProvider方法的代码,如下
private ViewModelProvider getViewModelProvider(
ViewModelStoreOwner owner, Context context) {
return new ViewModelProvider(
owner,
new ViewModelProvider.Factory() {
@NonNull
@Override
@SuppressWarnings("unchecked")
public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
ActivityRetainedComponent component =
EntryPointAccessors.fromApplication(
context, ActivityRetainedComponentBuilderEntryPoint.class)
.retainedComponentBuilder()
.build();
return (T) new ActivityRetainedComponentViewModel(component);
}
});
}
可以看到这个方法创建了ViewModelProvider类,想必看到这里会意识到这个类与ViewModel有关,好了,先跟到这里。
再回到上面时序图上generatedComponent方法
这个方法的代码如下
上面的时序图是顺着componentManager方法跟下去的画的,这次来跟下generatedComponent方法,时序图如下
这个时序图有两个地方需要注意下,如下图
第一处方法的代码如下
重点是红框内的内容,先看下EntryPoints.get( activityRetainedComponentManager, ActivityComponentBuilderEntryPoint.class)这段代码,get方法的内容如下
这段代码要留意一下,在后面代码执行的时候还会调用到这里,只是参数component不同,这里就不具体的分析了,继续看从这里跟下去的时序图,如下
这里需要说明一下,时序图上面的ARComponentManager是ActivityRetainedComponentManager,为了方便画时序图就缩写了一下。
继续看下2处的代码,如下
这里的viewModelProvider的get方法,最终会调用到下面的方法
最后调用到红框标记的地方,看到这里有没有感觉mFactory.create方法似曾相识,如果忘记的话,这里我再贴一下代码,帮助回忆下前面内容
没错,这里就调用了文章前面跟到crate方法,好了,这里就可以继续往下看create方法的代码了,先看下
EntryPointAccessors.fromApplication(
context, ActivityRetainedComponentBuilderEntryPoint.class)
这段代码做了什么,fromApplication方法代码如下
这里又调用了EntryPoints的get方法,前面已经贴过代码了,这里就不看里面的代码了。这段代码调用后返回的对象是DaggerMyApplication_HiltComponents_SingletonC实例,后面分析就简单了,大家自己跟下就行,最终create方法执行完,返回的是ActivityRetainedCImpl对象。
好了,还记得我们现在是从哪里跟下来的吗?是从下面的方法,红框内的代码得到的ActivityRetainedCImpl对象,
然后这个方法调用完,返回的是ActivityCImpl对象。好了,到这里终于快结束了,到这里我们只分析完了Hilt_MainActivity类的inject方法的前半部分
接着就是调用了ActivityRetainedCImpl的injectMianActivity方法,代码如下
最后调用到MainActivity_MembersInjector.injectModel(instance, new ActivityModel());这句代码。injectModel的代码如下
好了,这里就把ActivityModel注入到了MainActivity中。
纳尼,好像不对,这里还是没有解释生成的ActivityModel_Factory类的作用呀!是呀,还是没有发现ActivityModel_Factory类的作用呀,想要发现ActivityModel_Factory类的作用,还需要稍微修改下代码,新建Activity2Model类
里面的代码如下
在修改ActivityModel类中的代码如下
好了,现在再来看ActivityRetainedCImpl的injectMianActivity方法的代码
可以发现injectMainActivity2中的代码和前面的已经不一样了,好,继续往下跟,看下和以前不一样的地方,就是
activityModel的代码
好了,总算找到了ActivityModel_Factory了,到这里也就知道为什么Hilt会为我们生成xxx_Factory类了。
总结
文章首先是分析了Hilt_MainActivity,发现最后和Hilt_MyApplication一样会走到DaggerMyApplication_HiltComponents_SingletonC类中,最后调用到ActivityCImpl类中的injectMainActivity方法实现依赖注入,然后由分析了一下为什么Hilt会生成xxx_Factory类,以及它的作用。文章只讲解了重要的代码,如果有不理解的地方可以跟着文章中的时序图自己分析下,多分析分析,就会理解了。