Hilt原理分析一(Hilt技术概览)

简介: Hilt原理分析一(Hilt技术概览)

系列文章

在分析Hilt的原理之前,先搞清楚Hilt的一些黑魔法,这样在后面的原理分析的时候,才不会疑惑一些类是怎么冒出来的,以及为什么要多出这些类。

既然是原理分析,肯定离不开代码,因为这一节主要是要搞清楚Hilt整体的设计原理,所以我们先从最简单,也是使用Hilt必不可少的一步开始,对自定义的Application使用@HiltAndroidApp注解,源码如下

@HiltAndroidApp
class MyApplication : Application() {
}

只从这段代码,也看不出什么,那么为什么在使用Hilt的时候必须要加入这段代码呢?既然源码看不出什么,那么就看下经过编译后会有什么变化。

编译后的变化

代码编译后的一些产物会出现在模块的build/intermediates目录下,进入这个目录会发现有一个hilt的文件夹,看下里面的文件,如下

b0f0167ff026204ebd05b582c058d32.png

可以发现这里的四个类都与MyApplicaiton有关,将这四个类大致的看了一下,会发现Hilt_MyApplication类与MyApplication关系最大,可以看下代码

d8ee46a494041daa33225e9bb76b522.png

发现Hilt_MyApplication继承Application,到这里就有疑问了,我们自己写的MyApplication是继承Application的,这里又有一个继承Application的,而Android的一个进程只有一个Application类,那么这个编译后生成的类,和我们自己的Application有什么关系呢?想要知道答案,我们就看下最后生成的dex文件里,它们两个的关系。

Hilt_MyApplication与MyApplication

用Android Studio自带分析apk的工具打开编译后的apk,结构如图

042b2ab1a3e8de4ff82bea1d89143ae.png

依次查找这几个dex文件,最后在classes4.dex文件中找到了MyApplication,查看编译后的字节码如下

819d6d3566bfc8c1f78b728045cc38e.png

可以看到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文件的过程,如图

08c7a9aef9c0dd8e6e7cd4ae0cc8d2e.png

过程就是源码->class文件->dex文件,像上面第一个问题提到的APT技术的处理时机,就是在源码->class文件这一步,就是上图第一个红色虚线那里做的处理。

怎么让MyApplication继承Hilt_MyApplication的呢?

第二个问题就是在class文件->dex文件这一步做的处理,这里用到的技术就是修改字节码,常用的修改字节码的库是“ASM”,当然Hilt对字节码的处理也是用的这个库,可以在看下经过增加了ASM处理步骤后的图,比较下与上图有什么不同

d1ae0f446c3123e6919ee8dfb1155aa.png

就是在class文件->dex文件这一步用ASM对字节码文件做修改,就是这一步修改了字节码,让MyApplication继承至Hilt_MyApplication的。到这里又会有问题产生,那么Hilt是怎么干涉编译过程,利用ASM修改字节码的呢?

这个问题就涉及到Gradle的Plugin了,不了解Gradle的Plugin可以看下我的这篇文章,还记得导入Hilt的一些步骤吗?如下

98297e76e2679c9ccc72c63d4b25bc2.png

红框内的就是引入Hilt的Gradle的Plugin,通过Hilt的Plugin就可以在编译的过程插入自己的一些处理逻辑。

简单的看下Hilt的Plugin插件的源码,文件在/Users/xxx/.gradle/caches/modules-2/files-2.1/com.google.dagger/hilt-android-gradle-plugin目录下,

7be81157b979cd750f961bf0e5021cd.png

这里是根据Gradle插件的版本不同,做不同的处理,接着看下继承HIlt_XXX 的核心源码,如下

9a4fd1e038b0bc430f8feb8793bd46c.png

其实,问题2 涉及的做技术还是比较多的,这里我总结下用到的主要技术,不了解的话可以自己查阅相关资料

  • ASM
  • Gradle的Plugin
  • Gradle的Transform

看到这里是不是对Hilt的黑魔法有了基本的了解了呢?相信有了这些基本的认知,后面对源码的分析的文章,你一定会理解的更好。

总结

本文主要是回答了可能对Hilt的一些疑问,如生成的这些类与我们自己的类的关系,这些类是怎么产生出来的以及Hilt是怎么做到让我们自己的类来继承Hilt生成的类的。 文章主要是介绍Hilt利用了什么技术做到这些的,关于里面用到的一些技术,并不是本文的重点,如果不了解相关技术,可以自己查阅资料,相信了解了相关知识后,你会对Hilt有更深的理解。


相关文章
|
6月前
|
存储 安全 Android开发
从 Component Tree 视角看 Dagger 到 Hilt 的演变
从 Component Tree 视角看 Dagger 到 Hilt 的演变
98 0
|
移动开发 ARouter 开发工具
开源最佳实践:Android平台页面路由框架ARouter
为了更好地让开发者们更加深入了解阿里开源,阿里云云栖社区在3月1号了举办“阿里开源项目最佳实践”在线技术峰会,直播讲述了当前阿里新兴和经典开源项目实战经验以及背后的开发思路,在本次在线技术峰会上,阿里云资深开发工程师刘志龙分享了Android平台页面路由框架ARouter的技术方案、解决的问题以及在实际场景中的最佳实践。
47353 2
|
Java 数据库 Android开发
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(三)
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(三)
224 0
|
XML Java 程序员
插件化框架设计(二) Android 资源加载机制详解(一)
Android 提供了一种非常灵活的资源系统,可以根据不同的条件提供可替代资源。因此,系统基于很少的改造就能支持新特性,比如 Android N 中的分屏模式。这也是 Android 强大部分之一。本文主要讲述 Android 资源系统的实现原理,以及在应用开发中需要注意的事项。
213 0
|
Android开发
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(四)
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(四)
235 0
|
Android开发 容器
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(二)上
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(二)
128 0
|
Android开发 容器
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(二)下
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(二)
108 0
|
程序员 Android开发 容器
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(一)上
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(一)
94 0
|
Android开发 容器
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(一)下
使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高(一)
153 0