系列文章
在分析Hilt的原理之前,先搞清楚Hilt的一些黑魔法,这样在后面的原理分析的时候,才不会疑惑一些类是怎么冒出来的,以及为什么要多出这些类。
既然是原理分析,肯定离不开代码,因为这一节主要是要搞清楚Hilt整体的设计原理,所以我们先从最简单,也是使用Hilt必不可少的一步开始,对自定义的Application使用@HiltAndroidApp
注解,源码如下
@HiltAndroidApp class MyApplication : Application() { }
只从这段代码,也看不出什么,那么为什么在使用Hilt的时候必须要加入这段代码呢?既然源码看不出什么,那么就看下经过编译后会有什么变化。
编译后的变化
代码编译后的一些产物会出现在模块的build/intermediates
目录下,进入这个目录会发现有一个hilt
的文件夹,看下里面的文件,如下
可以发现这里的四个类都与MyApplicaiton
有关,将这四个类大致的看了一下,会发现Hilt_MyApplication
类与MyApplication
关系最大,可以看下代码
发现Hilt_MyApplication
继承Application,到这里就有疑问了,我们自己写的MyApplication
是继承Application的,这里又有一个继承Application的,而Android的一个进程只有一个Application类,那么这个编译后生成的类,和我们自己的Application有什么关系呢?想要知道答案,我们就看下最后生成的dex文件里,它们两个的关系。
Hilt_MyApplication与MyApplication
用Android Studio自带分析apk的工具打开编译后的apk,结构如图
依次查找这几个dex文件,最后在classes4.dex
文件中找到了MyApplication
,查看编译后的字节码如下
可以看到MyApplication
继承了HIlt_MyApplication
,到这里算是搞明白了它们两个的关系。关于Hilt_MyApplication
具体的作用,下篇文章会详细介绍。那么问题来了,Hilt是怎么做到生成Hilt_MyApplication
类以及怎么让MyApplication
继承Hilt_MyApplication
的呢?
Hilt的黑魔法
不知道HIlt原理的话,会觉得下面的两个问题是黑魔法
- Hilt是怎么做到生成
Hilt_MyApplication
类? - 怎么让
MyApplication
继承Hilt_MyApplication
的呢?
如果知道原理的话,就会觉的“哦,原来是这么回事”。
Hilt是怎么做到生成Hilt_MyApplication
类?
先来看第一个问题,还记得吗?在MyApplication
类上面有@HiltAndroidApp
注解,其实生成HIlt_MyApplication
类,就用到了这个注解。用到的技术就是Annotation Processing Tool
(简称APT),
APT 是一种处理注释的工具, 它对源代码文件进行检测找出其中的注解,并使用注解进行额外的处理。
通俗的解释一下就是: 在源码编译时查找特特定注解标记的类、字段或者方法,对这个注解标记的类、字段或者方法做一些额外的处理,可以生成新的代码,增加业务逻辑等。 这里生成Hilt_MyApplication
类就是用到的APT技术,不了解这个技术的话,可以查找一些资料,这个不是本文的重点。
再看下第二个问题,这个就说来话长了,因为涉及的内容较多,这里就长话短说,说下用到的技术,不理解的话,也是需要自己查阅相关资料。看下由Java或Kotlin生成dex文件的过程,如图
过程就是源码->class文件->dex文件,像上面第一个问题提到的APT技术的处理时机,就是在源码->class文件这一步,就是上图第一个红色虚线那里做的处理。
怎么让MyApplication
继承Hilt_MyApplication
的呢?
第二个问题就是在class文件->dex文件这一步做的处理,这里用到的技术就是修改字节码,常用的修改字节码的库是“ASM”,当然Hilt对字节码的处理也是用的这个库,可以在看下经过增加了ASM处理步骤后的图,比较下与上图有什么不同
就是在class文件->dex文件这一步用ASM对字节码文件做修改,就是这一步修改了字节码,让MyApplication
继承至Hilt_MyApplication
的。到这里又会有问题产生,那么Hilt是怎么干涉编译过程,利用ASM修改字节码的呢?
这个问题就涉及到Gradle的Plugin了,不了解Gradle的Plugin可以看下我的这篇文章,还记得导入Hilt的一些步骤吗?如下
红框内的就是引入Hilt的Gradle的Plugin,通过Hilt的Plugin就可以在编译的过程插入自己的一些处理逻辑。
简单的看下Hilt的Plugin插件的源码,文件在/Users/xxx/.gradle/caches/modules-2/files-2.1/com.google.dagger/hilt-android-gradle-plugin
目录下,
这里是根据Gradle插件的版本不同,做不同的处理,接着看下继承HIlt_XXX
的核心源码,如下
其实,问题2 涉及的做技术还是比较多的,这里我总结下用到的主要技术,不了解的话可以自己查阅相关资料
- ASM
- Gradle的Plugin
- Gradle的Transform
看到这里是不是对Hilt的黑魔法有了基本的了解了呢?相信有了这些基本的认知,后面对源码的分析的文章,你一定会理解的更好。
总结
本文主要是回答了可能对Hilt的一些疑问,如生成的这些类与我们自己的类的关系,这些类是怎么产生出来的以及Hilt是怎么做到让我们自己的类来继承Hilt生成的类的。 文章主要是介绍Hilt利用了什么技术做到这些的,关于里面用到的一些技术,并不是本文的重点,如果不了解相关技术,可以自己查阅资料,相信了解了相关知识后,你会对Hilt有更深的理解。