使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高
Posted bug樱樱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高相关的知识,希望对你有一定的参考价值。
依赖注入为何物
既然你已经点进来了,想必已经知道什么是依赖注入了吧,什么?!你还不知道什么是依赖注入吗,那你更要继续往下读了。
首先,来看看依赖注入的定义:
依赖注入就是参数传递
噢噢,我的老伙计,希望你并没有因为这个简单的定义而直接离开本文,我当然知道参数传递是每一位入门级程序员都掌握的基本能力,但为什么要用其他工具来完成这个参数传递呢,因为随着项目的膨胀,项目组件的不断扩大,组件之间的耦合关系也会愈发复杂,我们用一个实际例子来看看
项目膨胀导致的参数传递问题
假设我有一个这样的场景,我需要构造一个车子,车子又有其他零件,零件又有子零件。
/**
* 车子
*/
class Car(
private val steeringWheel: SteeringWheel,
private val wheel: Wheel
)
/**
* 方向盘
*/
class SteeringWheel(private val color:String)
/**
* 轮子
*/
class Wheel(private val steel: Steel)
/**
* 钢圈
*/
class Steel(private val circle:Int)
复制代码
那么我要如何构造这个车子呢,代码如下(多个场景表示在项目中存在多处需要构造Car的地方):
//模拟场景1
fun test1()
Car(SteeringWheel("红色"), Wheel(Steel(30)))
//模拟场景2
fun test2()
Car(SteeringWheel("蓝色"), Wheel(Steel(40)))
//模拟场景3
fun test3()
Car(SteeringWheel("黑色"), Wheel(Steel(50)))
All right!所有的一切都没问题,项目正常上线,然后某天项目经理跟你说:嘿,这位码农,麻烦给钢圈加个花边吧。你按捺住内心想打人的冲动,然后打开AS,给钢圈加一个属性,不出意外的是,项目出现了一大堆报错,原来是因为汽车包含了轮子,轮子包含了花边,于是所有构造汽车的代码都报错了,于是你修改了代码,变成了如下:
/**
* 钢圈
*/
class Steel(private val circle:Int,private val lace:String)
//模拟场景1
fun test1()
Car(SteeringWheel("红色"), Wheel(Steel(30,"花边1")))
//模拟场景2
fun test2()
Car(SteeringWheel("蓝色"), Wheel(Steel(40,"花边2")))
//模拟场景3
fun test3()
Car(SteeringWheel("黑色"), Wheel(Steel(50,"花边3")))
加班到12点的你终于确认了所有的代码都被修改,提交测试上线,但是回到床位后的你依然战战兢兢的思考着今天的问题,万一下一次项目经理又要你添加其他属性呢,一想到又要加班熬夜你迅速起身疯狂百度,于是你了解到了工厂模式。
于是你又起床新增了一个Car的工厂接口
interface CarFactory
fun build():Car
object CarAFactory:CarFactory
override fun build(): Car
return Car(SteeringWheel("红色"), Wheel(Steel(30,"花边1")))
object CarBFactory:CarFactory
override fun build(): Car
return Car(SteeringWheel("蓝色"), Wheel(Steel(40,"花边2")))
object CarCFactory:CarFactory
override fun build(): Car
return Car(SteeringWheel("黑色"), Wheel(Steel(50,"花边3")))
//模拟场景1
fun test1()
CarAFactory.build()
//模拟场景2
fun test2()
CarBFactory.build()
//模拟场景3
fun test3()
CarCFactory.build()
情况看起来好了很多,调用端已经没有具体的构造代码了,一切的构造都交给了工厂类,但是一旦这些类的属性膨胀起来后,会出现许许多多的工厂类,甚至工厂类本身都会出现属性配置,调用端的代码依然需要手动去修改,也许你进一步学习了抽象工厂,但是这些手段总给你一种感觉:面多了加水,水多了加面。此时的你迫切希望有一种更加解耦,更加无侵入性的手段帮你去实现对象的构建。
因此,假设有一个容器,他内部定义了如何构建各个零部件的构建方法,我们只需要告诉容器我需要什么,容器就会自动返回成品,因此我们也不需要手动去实现工厂类,那该多好?
因此,我隆重推荐谷歌Jetpack里面的组件------Hilt
为什么是Hilt?
如果你之前了解过安卓端依赖注入相关的框架,那么你肯定听过Okio,Dagger2,Hilt这三个框架,那么为什么选择Hilt呢,我的理由如下:
- Hilt基于Dagger2封装的框架,即在Dagger2的基础上加了一些安卓的场景化配置,也就是说,使用Hilt可以完成Dagger2的工作,同时避免了安卓场景下的部分模板代码。
- Hilt是Jetpack组件,和其他Jetpack组件协作良好,例如ViewModel,Compose,WorkManager都可以和Hilt无缝协作。
Hilt的初体验
给顶层的build.gradle添加插件
buildscript
...
dependencies
...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
给所有使用Hilt的Module对应的gradle添加如下配置:
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'
dependencies
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
给项目的Application添加注解@HiltAndroidApp,添加这个注解的含义是给Application生成一个顶级容器,容器的生命周期跟随Application。
@HiltAndroidApp
class ExampleApplication : Application() ...
接下来,我们要给对应的android组件提供依赖(也就是对组件完成参数传递的),使用注解@AndroidEntryPoint,以Activity为例。
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() ...
然后,我们就可以给Activity注入我们想要的依赖了,例如注入一个Adapter,使用@Inject注释添加到我们想要注入的属性上面(切记,被注入的属性不能是private否则会报错)。
@AndroidEntryPoint
class ExampleActivity:AppCompatActivity()
//注入,不用手动实例化
@Inject
lateinit var analyticsAdapter: AnalyticsAdapter
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
//直接调用对象,没有实例化代码
analyticsAdapter.analytics()
class AnalyticsAdapter
fun analytics()
非常神器,我们并没有看到adapter有被初始化的地方了,因为Hilt帮我们完成了初始化,也就是帮我们完成了Adapter的依赖注入!
然而当你满心欢喜的尝试去运行上面这段代码的时候,崩溃了!错误是analyticsAdapter并没有被正确实例化,这是什么原因呢,道理很简单:我们只是告诉了Hilt,我们需要一个AnalyticsAdapter,但是Hilt却并不知道AnalyticsAdapter该如何创建,解决问题也很简单,我们告诉Hilt如何创建它不就好了。
我们给AnalyticsAdapter的构造方法添加一个@Inject注释,告诉Hilt我们用空的构造方法来构建AnalyticsAdapter。
代码能运行了!
同时细心的发现代码左侧出现了两个小图标,这是一开始添加的插件的功能,点击一下AnalyticsAdapter对象左侧有红色向上箭头的图标,会发现跳转到了AnalyticsAdapter的构造函数;点击AnalyticsAdapter构造函数左侧的3个灰方块组成的小图标,则跳转到了AnalyticsAdapter对象。
上诉操作说明了当我们点击被注入的对象左侧的小图标的时候,实际上我们是在尝试“查找注入的来源”,当我们点击构造函数左侧的小图标的时候,实际上我们是在尝试“查找注入的去向”,通过这两个小图标我们可以快速查找到当前的对象是如何被注入的。
此刻,项目经理出现了,让我们添加某个功能,体现在代码中则是,Adapter需要外部传入一个对象,于是我们新增一个成员属性到AnalyticsAdapter的构造函数中去。
运行程序,不出意外的崩溃了。复盘原因,非常简单,因为我们告诉了Hilt如何创建AnalyticsAdapter,即使用它的带参构造函数去构建,但是Hilt在调带参构造函数的时候,发现自己不懂如何创建NetworkService。
参考当初构建AnalyticsAdapter的方式,我们继续给NetworkService的构造参数也添加一个@Inject注解,熟悉的图标又出现了,Hilt这回懂得了如何正确创建NetworkService。
运行代码,正确!好的,刚才给Adapter新增了一个成员属性,让我们再看看Activity的代码,完全没有发生变化。
我们通过了Hilt来帮我们完成了参数的传递(注意,只是辅助完成了这个过程并不是消灭了参数传递),对于Activity来说,他只是需要Adapter,他并不在乎Adapter的内部构建过程,所以Adapter内部再怎么发生剧烈的变化,Activity的代码都是不用去修改的,非常的完美。
课后小练习:
下面提供两个小练习让你去体验使用Hilt实现依赖注入的低耦合性
1.给AnalyticsAdapter扩充第二个成员变量,类型为你自己定义的类(可以参考NetworkService)
2.给NetworkService增加一个成员变量
好了,本文到此就结束,关于Hilt的话题我们才刚刚起步,还有许多问题等待着我们去解决,例如如何注入一个接口?那些我们不能修改代码的第三方类如何注入(因为不能修改构造函数)?如何保证注入的都是同一个对象(实现单例)?那么下期我将更详细地逐一解决这些问题。
作者:晴天小庭
链接:https://juejin.cn/post/7123148433367498766
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
一、架构师筑基必备技能
1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……
二、Android百大框架源码解析
1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程
三、Android性能优化实战解析
- 腾讯Bugly:对字符串匹配算法的一点理解
- 爱奇艺:安卓APP崩溃捕获方案——xCrash
- 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
- 百度APP技术:Android H5首屏优化实践
- 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
- 携程:从智行 Android 项目看组件化架构实践
- 网易新闻构建优化:如何让你的构建速度“势如闪电”?
- …
四、高级kotlin强化实战
1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》
-
从一个膜拜大神的 Demo 开始
-
Kotlin 写 Gradle 脚本是一种什么体验?
-
Kotlin 编程的三重境界
-
Kotlin 高阶函数
-
Kotlin 泛型
-
Kotlin 扩展
-
Kotlin 委托
-
协程“不为人知”的调试技巧
-
图解协程:suspend
五、Android高级UI开源框架进阶解密
1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
六、NDK模块开发
1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习
七、Flutter技术进阶
1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)
…
八、微信小程序开发
1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证卡片免费领取↓↓↓
以上是关于使用Hilt完成依赖注入,让你的安卓代码层次有几层楼那么高的主要内容,如果未能解决你的问题,请参考以下文章