系列文章
上一篇文章的末尾,提到了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类,以及它的作用。文章只讲解了重要的代码,如果有不理解的地方可以跟着文章中的时序图自己分析下,多分析分析,就会理解了。