DI(Dependency Injection),即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

最近业务同学需要接入谷歌推的Hilt框架。因为哔哩哔哩的业务上很容易出现业务层面的交叉,而因为项目完成了大量的组件化拆分。由于不希望业务之间产生相互引用,所有在技术评估完成之后我们决定由我们部门来对Hilt进行接入。

方案介绍

接入Hilt

摘自官方文档 使用 Hilt 实现依赖项注入

首先先声明下dagger.hilt.android.plugin相关的plugin。

buildscript {...dependencies {...classpath 'com.google.dagger:hilt-android-gradle-plugin:2.35.1'}
}
复制代码

其次由于hilt一大部分相关的都是基于kapt的代码生成逻辑,所以我们要在使用到hilt的模块的build.gradle中都定义如下相关的。

...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'android {...
}dependencies {implementation "com.google.dagger:hilt-android:2.35.1"kapt "com.google.dagger:hilt-android-compiler:2.35.1"
}
复制代码

我们需要给我们的Application增加一个注解。

@HiltAndroidApp
class ExampleApplication : Application() {  }
复制代码

根据官方接入文档哦,我们组只要把Application只要打上@HiltAndroidApp的注解,就可以完成这部分接入能力了。

Hilt在组件化

但是但是官方有个声明是这样的。

Hilt 代码生成操作需要访问使用 Hilt 的所有 Gradle 模块。编译 Application 类的 Gradle 模块需要在其传递依赖项中包含所有 Hilt 模块和通过构造函数注入的类。

从这部分说明上来看,这个注解最好是能放在com.android.application模块中, 这样就能保证依赖到所有的子模块中去了。

但是实际我们在使用过程中,由于com.android.application模块还是有一些代码量的,而由于kapt代码生成机制,需要先将kotlin代码转化成java代码,之后才能生成ast语法树。

根据ci上的实验结果,在com.android.application模块下kapt耗时在30s左右,而整体编译时间大概为3分钟左右。这种耗时我个人觉得还是属于不能接受的。

所以我们调整了下这部分代码。这次建立了一个壳module,这边只有HiltApplication的注解相关。然后将这个module依赖了所有业务仓库,按照编译逻辑来说,基于gradle taskdepend逻辑,他会在application模块编译之前,所有业务模块编译之后,这样能保证hilt生成的代码逻辑正常。

同时由于是一个空工程,我们把空工程定义为bundle-kapt,所以整体来说对于编译速度影响会变到最小。让各位大佬看下我们后续的优化结果。

上述是我最后截图出来的结果,我们将一个耗时大概30s的任务优化到3s,其实效果上来说已经非常明显,达到我们想要的预期了已经。

当然如果后续hilt支持了ksp之后,这部分速度应该可以更快,毕竟我么可以直接抛弃java语法树了吗。

出现了点小问题

这两天业务方实际在使用过程中,突然反馈说貌似我们接入的Hilt貌似不行啊,进入到页面直接崩溃了。

有一说一,一脸懵逼。先看看异常吧。初一开始我以为是kapt没有生成好或者别的什么原因导致的。

com.xxxxxx.xxxxxx}: java.lang.ClassCastException: xxxxx.DaggerHiltApplication_HiltComponents_SingletonC$ActivityRetainedCImpl$ActivityCImpl cannot be cast to xxxxx_GeneratedInjector
复制代码

只能一步步调试咯,我打开项目开启编译项目,之后进入蛮长的等待过程中。10分钟过去了终于好了。

由于Hilt使用了kapt,所以很自然的打开了build/generated/source/kapt文件路径,之后我看了下DaggerHiltApplication_HiltComponents_SingletonC这个类的生成。

ActivityRetainedCImpl从这里我大概猜测出了一小部分Hilt原理,通过收集不同子Module的抽象接口,然后把这部分能力聚合在HiltApplication中,举个例子Hilt_BangumiDetailActivityV3这个就是一个子业务内的DI注入的一个类的实现。

突然这个时候我想到了一件事哦,也就是说我们的bundle-kapt模块,其实它的实际编译产物会根据接入业务的不同而产生实际的变更。也就是说虽然这个模块的代码没有发生变更,但是由于子业务增加了注解和代码变更,导致了这个模块的kapt还是需要重新执行,这样才能保证输出的产物是变化的。

然而我们的项目之前由于工程结构太庞大了,可能有30-40个Module,所有我们将一部分没有变更的代码产物化,也就是基于commit变成了一个个aar或者jar发布到了远端。之后根据commit来重新定向到产物。

bundle-kapt这个模块也很不幸,被当做了一个静态模块,变成了一个远端的产物,之后即时业务添加了再多的注入相关的,因为bundle-kapt没有参与编译,所以注入的能力就出错了。

作者:究极逮虾户
链接:https://juejin.cn/post/6978407567047262222
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

哔哩哔哩在Hilt组件化的使用 | 技术探索相关推荐

  1. [Android Pro] 终极组件化框架项目方案详解

    cp from : https://blog.csdn.net/pochenpiji159/article/details/78660844 前言 本文所讲的组件化案例是基于自己开源的组件化框架项目 ...

  2. Android 基于注解IOC组件化/模块化的架构实践

    当前参与的项目历史也很久远,第一行代码据说是写于2014年的某一天,那时Android用的ide还是Eclipse.那时Android还没有很好的架构指导(mvp.mvvm).那时Android最新的 ...

  3. 宜人贷-iOS客户端组件化介绍

    文章简介: 本文将从三个方面讲解我们组件化项目.第一部分,我们将介绍组件化的意义和业内组件化的进程:第二方面我们将具体介绍组件化所使用的技术,以及组件化过程中所面对的问题:而第三方面,我们会展示我们组 ...

  4. 跨桌面端之组件化实践

    本文主要介绍了千牛PC跨端框架中,我们关于组件化部分的思考.方案选择.遇到的一些问题和解法. 此文为本系列文章第三篇, 第一篇:跨全端SDK技术演进 第二篇:跨桌面端之Web容器演进 本文:跨桌面端之 ...

  5. Android 组件化架构概要,ffmpeg音视频开发实战陈超

    ChatModule ContactModule FindModule MeModule BaseModule 分别对应的是微信,联系人,发现,我和基类. 3.自定义Gradle 我们在Project ...

  6. Android 组件化架构概要,熬夜整理Android高频面试题

    模块 :指具体的业务逻辑模块,比如微信主页的四个页面,我们就可以定义为四个模块,由于模块的对象是业务,所以比组件的广度来讲要大许多,因为随着他的业务进展,他会包含越来越多的组件. 库 :单一职责的提供 ...

  7. Android组件化和插件化开发

    项目发展到一定程度,就必须进行模块的拆分.模块化是一种指导理念,其核心思想就是分而治之.降低耦合.而在 Android 工程实践,目前有两种途径,一个是组件化,一个是插件化. 组件化开发 说起组件化少 ...

  8. Android组件化和插件化开发,android开发工程师月薪

    开发调试时不需要对整个项目进行编译,每个模块可独立编译,提高了编译速度. 多人合作时可以只关注自己的业务模块,把某一业务当成单一项目来开发,可以提升开发,测试效率. 可以灵活的对业务模块进行组装和拆分 ...

  9. 微信小程序仿哔哩哔哩视频组件

    微信小程序视频组件仿照哔哩哔哩 微信小程序仿照哔哩哔哩(包含源码获取) 效果如下图 一.项目介绍 项目为简单的小程序代码片段,不包含后端,只通过原生的小程序语言开发,使用官方原生的 video,没有使 ...

最新文章

  1. ASP.NET之父谈ASP.NET AJAX
  2. Infortrend推出超大容量存储解决方案
  3. 这个比肩ImageNet的数据集遭MIT紧急下架,原因令人愤怒
  4. redis 集合操作
  5. 关于反射GetType().GetProperties()的疑惑
  6. LC_ALL=C表示什么?
  7. uploadify多文件上传插件
  8. stc单片机入门c语言,谈谈单片机入门
  9. Recall(召回率) Precision(准确率) F-Measure E值 sensitivity(灵敏性) specificity(特异性)漏诊率 误诊率 ROC AUC
  10. MySQL 在 Mac 环境下的安装
  11. charles 中文_抓包工具--charles(青花瓷)及获取AppStore数据包
  12. ubuntu命令整理中
  13. numpy教程:ndarray属性、内建函数及其运算、迭代
  14. Arcgis Android API开发之离线地图
  15. php中js中文传值乱码,php解析JSON中文乱码问题的解决方法
  16. 【STM32】 JDY-31蓝牙模块
  17. 计算机排版系统程序,《计算机排版系统.doc
  18. java多态理解通俗,说说 Java 多态那些事儿~
  19. 如何主动退出小程序(微信小程序)
  20. Ubuntu息屏后唤醒的花屏问题

热门文章

  1. Android屏幕适配方案
  2. [FAQ11783][NW]MVNO忽略国内漫游(ignore national roaming)
  3. 身份证OCR识别发展史
  4. EXCEL数据处理相关操作
  5. 同花顺_代码解析_技术指标_T、U
  6. Refused to execute inline script because it violates the following Content Security Policy directive
  7. Mybatis-主键回填
  8. 计算机毕业设计springboot基于VUE电脑城摊位出租系统
  9. type object ‘TestGetToken‘ has no attribute ‘test_right_gett_token‘
  10. vbnet如何注释_克里斯出售股票为VBNET Develo提供XML注释和文档生成