使用Hilt实现Android依赖注入(DI:dependency-injection)

什么是依赖注入?

软件工程中,依赖注入(dependency injection)的意思为,给予调用方它所需要的事物。 “依赖”是指可被方法调用的事物。依赖注入形式下,调用方不再直接使用“依赖”,取而代之是“注入” 。“注入”是指将“依赖”传递给调用方的过程。在“注入”之后,调用方才会调用该“依赖”[1]。传递依赖给调用方,而不是让让调用方直接获得依赖,这个是该设计的根本需求。

注:编程语言层次下,“调用方”为对象和类,“依赖”为变量。在提供服务的角度下,“调用方”为客户端,“依赖”为服务。

该设计的目的是为了分离关注点,分离调用方和依赖,从而提高可读性以及代码重用性

依赖注射是控制反转的最为常见的一种技术。

引用自 维基百科

简介

依赖项注入是一种在编程中运用广泛的技术,非常适用于 Android 开发。遵循依赖项注入的原则可以为良好的应用架构奠定基础。

实现依赖项注入可为您带来以下优势:

  • 重用代码
  • 易于重构
  • 易于测试

Hilt 是 Android 颇具特色的依赖项注入库,可减少在项目中使用手动依赖项注入时产生的样板代码。手动依赖项注入要求您手动构造每个类及其依赖项,并借助容器来重复使用和管理依赖项。

Hilt 通过为项目中的每个 Android 组件提供容器并自动为您管理容器生命周期,提供了一种在应用中执行依赖项注入的标准方法。这通过利用热门依赖项注入库 Dagger 实现。

前提条件

  • 您有 Kotlin 语法经验。
  • 您了解依赖项注入为什么对应用至关重要。

将 Hilt 添加到项目中

首先,将 hilt-android-gradle-plugin 插件添加到项目的根级 build.gradle 文件中:

1
2
3
4
5
6
7
8
buildscript {
...
ext.hilt_version = '2.28-alpha'
dependencies {
...
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
}
}

Tips:这里有一个坑,kotlin的版本如果是 1.5.0 的话,可能会在后续使用的编译时产生如下错误:

1
2
3
4
5
6
7
Execution failed for task ':app:kaptDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask$KaptExecutionWorkAction
> java.lang.reflect.InvocationTargetException (no error message)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

image-20211221111905297

出现的原因:

Kotlin 的版本过高。

解决办法:

降低 Kotlin 的版本(我把 Kotlin 的版本改成 1.4.0 之后,然后编译通过了)。

参考链接

然后,为在 app 模块中使用 gradle 插件,我们应在 app/build.gradle 文件中指定它,具体方法为:将 gradle 插件添加到此文件的顶部、kotlin-kapt 插件之下:

1
2
3
4
5
6
7
...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

android {
...
}

然后,Hilt 依赖项会包含在项目的同一个 app/build.gradle 文件中:

1
2
3
4
5
6
...
dependencies {
...
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
}

最后,点击右上角的 Sync now 按钮同步项目,这个时候会下载包括 Hilt 在内的所有库。自此我们的准备工作就完成了。

在应用中使用 Hilt

在继承自 Application 类的上方添加 @HiltAndroidApp 注解。

1
2
3
4
@HiltAndroidApp
class App : Application() {
...
}

Hilt 模块

新建一个单例的 UserModel 类,然后在里面编写如下代码:

1
2
3
4
5
6
7
8
9
@Module
@InstallIn(ActivityComponent::class)
object UserModel {

@Provides
fun provideUser(): User {
return User("张三", "123456")
}
}

使用 Hilt 实现字段注入

Hilt 目前支持以下 Android 类型:Application(通过使用 @HiltAndroidApp)、ActivityFragmentViewServiceBroadcastReceiver

Hilt 仅支持扩展 FragmentActivity(例如 AppCompatActivity)的 activity 和扩展 Jetpack 库 Fragment 的 fragment,不支持 Android 平台中的 Fragment(现已弃用)。

警告:Hilt 不支持保留的 fragment。

如要执行字段注入,请对您希望由 Hilt 提供(或注入)的 Android 类字段使用 @Inject 注解。

警告:由 Hilt 注入的字段不能是私有字段。

将字段注入到 Activity 中

在 Activity 上添加 @AndroidEntryPoint 注解,即可使用依赖注入。

1
2
3
4
5
6
7
8
9
10
11
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

@Inject lateinit var user: User

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Toast.makeText(this, "$user", Toast.LENGTH_SHORT).show()
}
}

将字段注入到 Fragment 中

将注入到 Fragment 中时,需要先在其附属的 Activity 上添加 @AndroidEntryPoint 注解,然后再在 Fragment 上添加 @AndroidEntryPoint 注解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@AndroidEntryPoint
class HiltFragment: Fragment() {

@Inject lateinit var user: User

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.hilt_fragment, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Toast.makeText(context, "$user", Toast.LENGTH_SHORT).show()
}
}

Hilt & Dagger 注解

PDF文档下载链接

参考文章

依赖注入

在 Android 应用中使用 Hilt

java.lang.reflect.InvocationTargetException (no error message)

使用 Hilt 实现依赖项注入

请同学们点赞、评论、打赏+关注啦~


使用Hilt实现Android依赖注入(DI:dependency-injection)
https://blog.funkt.cn/2021/12/21/1473142338539847682/
作者
anjiemo
发布于
2021年12月21日
许可协议
未经作者授权,禁止转载