Hilt原理分析三(xxx_Factory的作用)

1,369 阅读4分钟

系列文章

上一篇文章的末尾,提到了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()
    }
}

编译运行下,打印的日志如下

image-20220514143351850.png

再看下编译后生成的文件,如下

image-20220514143446095.png

可以看到这里新生成了两个文件,Hilt也是通过这两个文件实现Activity中的依赖注入的,下面通过这两个文件来了解下Hilt在Activity实现依赖注入的原理。

Hilt_MainActivity分析

通过前面两篇的内容可以知道,MainActivity编译后会继承至Hilt_MainActivity,看下Hilt_MainActivity代码

image-20220514144121413.png

从上面的截图中可以看到,通过Hilt_MainActivity的构造方法会注册一个监听,当这个类与Context关联时会收到回调,然后继续调用inject方法,inject方法的代码如下

image-20220514144431624.png

因为inject方法调用的方法会较多,这里就画出调用的时序图,重要的地方再讲下代码,部分时序图如下

image-20220514145824062.png

这里看下时序图上的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方法

image-20220514215446480.png

这个方法的代码如下

image-20220514215640758.png

上面的时序图是顺着componentManager方法跟下去的画的,这次来跟下generatedComponent方法,时序图如下

Hilt_MainActivity inject方法分析1.png

这个时序图有两个地方需要注意下,如下图

image-20220514220349768.png

第一处方法的代码如下

image-20220514220509102.png

重点是红框内的内容,先看下EntryPoints.get( activityRetainedComponentManager, ActivityComponentBuilderEntryPoint.class)这段代码,get方法的内容如下

image-20220514220757634.png

这段代码要留意一下,在后面代码执行的时候还会调用到这里,只是参数component不同,这里就不具体的分析了,继续看从这里跟下去的时序图,如下

image-20220514221353042.png

这里需要说明一下,时序图上面的ARComponentManager是ActivityRetainedComponentManager,为了方便画时序图就缩写了一下。

继续看下2处的代码,如下

image-20220514221637555.png

这里的viewModelProviderget方法,最终会调用到下面的方法

image-20220514221757667.png

最后调用到红框标记的地方,看到这里有没有感觉mFactory.create方法似曾相识,如果忘记的话,这里我再贴一下代码,帮助回忆下前面内容

image-20220514222104184.png

没错,这里就调用了文章前面跟到crate方法,好了,这里就可以继续往下看create方法的代码了,先看下

EntryPointAccessors.fromApplication(
                    context, ActivityRetainedComponentBuilderEntryPoint.class)

这段代码做了什么,fromApplication方法代码如下

image-20220514222624743.png

这里又调用了EntryPointsget方法,前面已经贴过代码了,这里就不看里面的代码了。这段代码调用后返回的对象是DaggerMyApplication_HiltComponents_SingletonC实例,后面分析就简单了,大家自己跟下就行,最终create方法执行完,返回的是ActivityRetainedCImpl对象。

好了,还记得我们现在是从哪里跟下来的吗?是从下面的方法,红框内的代码得到的ActivityRetainedCImpl对象,

image-20220514223556412.png

然后这个方法调用完,返回的是ActivityCImpl对象。好了,到这里终于快结束了,到这里我们只分析完了Hilt_MainActivity类的inject方法的前半部分

image-20220514223809852.png

接着就是调用了ActivityRetainedCImplinjectMianActivity方法,代码如下

image-20220514224205466.png

最后调用到MainActivity_MembersInjector.injectModel(instance, new ActivityModel());这句代码。injectModel的代码如下

image-20220514224331128.png

好了,这里就把ActivityModel注入到了MainActivity中。

纳尼,好像不对,这里还是没有解释生成的ActivityModel_Factory类的作用呀!是呀,还是没有发现ActivityModel_Factory类的作用呀,想要发现ActivityModel_Factory类的作用,还需要稍微修改下代码,新建Activity2Model

image-20220514224729502.png

里面的代码如下

image-20220514224807582.png

在修改ActivityModel类中的代码如下

image-20220514224850983.png

好了,现在再来看ActivityRetainedCImplinjectMianActivity方法的代码

image-20220514225029210.png

可以发现injectMainActivity2中的代码和前面的已经不一样了,好,继续往下跟,看下和以前不一样的地方,就是

activityModel的代码

image-20220514225312100.png

好了,总算找到了ActivityModel_Factory了,到这里也就知道为什么Hilt会为我们生成xxx_Factory类了。

总结

文章首先是分析了Hilt_MainActivity,发现最后和Hilt_MyApplication一样会走到DaggerMyApplication_HiltComponents_SingletonC类中,最后调用到ActivityCImpl类中的injectMainActivity方法实现依赖注入,然后由分析了一下为什么Hilt会生成xxx_Factory类,以及它的作用。文章只讲解了重要的代码,如果有不理解的地方可以跟着文章中的时序图自己分析下,多分析分析,就会理解了。