Android Dagger-Hilt 依赖注入
Author: aa86799@163.com
date: 2020-09-09 00:10
文章目录
- 文档地址
- 依赖配置
- @HiltAndroidApp
- 将依赖项注入 Android 类
- @Inject 注入
- 定义 Hilt 绑定
- 使用 @Binds 注入接口实例
- 使用 @Provides 注入实例
- 为同一类型提供多个绑定,使用限定符 @Qualifier
- 预定义限定符:@ApplicationContext, @ActivityContext
- Hilt 组件
- 组件生命周期
- 组件作用域
- 组件层次结构
- 在 Hilt 不默认支持的类中注入依赖项
- 实例:普通类注入 不同的Retrofit(不同的baseUrl) 对象
- 实例:普通类 注入 Repository
- 使用 Hilt 注入 ViewModel 对象
- 使用 Hilt 注入 WorkManager
文档地址
https://developer.android.google.cn/training/dependency-injection/hilt-android
点击进入Hilt官网,了解更多细节
依赖配置
project/build.gradle
# 2021-05 hilt已发布正式版,最新版本,直接上hilt官网查看
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
app/build.gradle
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'android {...compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation "com.google.dagger:hilt-android:2.28-alpha"kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}
@HiltAndroidApp
@HiltAndroidApp
class ExampleApplication : Application() { ... }
@HiltAndroidApp
会触发 Hilt 的代码生成操作, 生成的代码包括应用的一个基类,该基类充当应用级依赖项容器
将依赖项注入 Android 类
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() { ... }
Hilt 目前支持以下 Android 类:
Application
(通过使用@HiltAndroidApp
)Activity
Fragment
View
Service
BroadcastReceiver
(直接用@AndroidEntryPoint注入不成功)- ContentProvider (直接用@AndroidEntryPoint注入不成功)
注意:在 Hilt 对 Android 类的支持方面还要注意以下几点:
- Hilt 仅支持扩展
ComponentActivity
的 Activity,如AppCompatActivity
。- Hilt 仅支持扩展
androidx.Fragment
的 Fragment。- Hilt 不支持保留的 Fragment。
@Inject 注入
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {@Inject lateinit var analytics: AnalyticsAdapter...
}
定义 Hilt 绑定
向 Hilt 提供绑定信息的一种方法是构造函数注入。在某个类的构造函数中使用 @Inject
注释,以告知 Hilt 如何提供该类的实例:
class AnalyticsAdapter @Inject constructor(@Inject lateinit var service: AnalyticsService
) { ... }
在本例中,AnalyticsService
是 AnalyticsAdapter
的一个依赖项。因此,Hilt 还必须知道如何提供 AnalyticsService
的实例。
使用 @Binds 注入接口实例
interface AnalyticsService {fun analyticsMethods()
}// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl @Inject constructor(...
) : AnalyticsService { ... }@Module
@InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {@Bindsabstract fun bindAnalyticsService(analyticsServiceImpl: AnalyticsServiceImpl): AnalyticsService
}
Hilt 模块 AnalyticsModule
带有 @InstallIn(ActivityComponent::class)
注释,因为您希望 Hilt 将该依赖项注入 ExampleActivity
。此注释意味着,AnalyticsModule
中的所有依赖项都可以在应用的所有 Activity 中使用。
使用 @Provides 注入实例
如果某个类不归您所有(因为它来自外部库,如 Retrofit、OkHttpClient
或 Room 数据库等类),或者必须使用构建器模式创建实例,也无法通过构造函数注入。
@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {@Providesfun provideAnalyticsService(// Potential dependencies of this type): AnalyticsService {return Retrofit.Builder().baseUrl("https://example.com").build().create(AnalyticsService::class.java)}
}
为同一类型提供多个绑定,使用限定符 @Qualifier
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AuthInterceptorOkHttpClient@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class OtherInterceptorOkHttpClient
方式一
@AuthInterceptorOkHttpClient
@Provides
fun m():OkHttpClient
方式二
@Provides
fun m(@AuthInterceptorOkHttpClient client: OkHttpClient):...
方式三
class ExampleServiceImpl @Inject constructor(@AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient
)
方式四
@AuthInterceptorOkHttpClient
@Inject lateinit var okHttpClient: OkHttpClient
与binds结合:(官方文档没写,猜想应该是可以的)
@Binds
@AuthInterceptorOkHttpClient
abstract fun bind(): OkHttpClient
预定义限定符:@ApplicationContext, @ActivityContext
class AnalyticsAdapter @Inject constructor(@ActivityContext private val context: Context,private val service: AnalyticsService
) { ... }
Hilt 组件
@InstallIn
注释中引用相应的组件。限定了注入的实例的生命周期范围。
Hilt 组件 | 注入器面向的对象 |
---|---|
ApplicationComponent
|
Application
|
ActivityRetainedComponent
|
ViewModel
|
ActivityComponent
|
Activity
|
FragmentComponent
|
Fragment
|
ViewComponent
|
View
|
ViewWithFragmentComponent
|
带有 @WithFragmentBindings 注释的 View
|
ServiceComponent
|
Service
|
组件生命周期
生成的组件 | 创建时机 | 销毁时机 |
---|---|---|
ApplicationComponent
|
Application#onCreate()
|
Application#onDestroy()
|
ActivityRetainedComponent
|
Activity#onCreate()
|
Activity#onDestroy()
|
ActivityComponent
|
Activity#onCreate()
|
Activity#onDestroy()
|
FragmentComponent
|
Fragment#onAttach()
|
Fragment#onDestroy()
|
ViewComponent
|
View#super()
|
视图销毁时 |
ViewWithFragmentComponent
|
View#super()
|
视图销毁时 |
ServiceComponent
|
Service#onCreate()
|
Service#onDestroy()
|
注意:
ActivityRetainedComponent
在配置更改后仍然存在,因此它在第一次调用Activity#onCreate()
时创建,在最后一次调用Activity#onDestroy()
时销毁。
组件作用域
Android 类 | 生成的组件 | 作用域 |
---|---|---|
Application
|
ApplicationComponent
|
@Singleton
|
View Model
|
ActivityRetainedComponent
|
@ActivityRetainedScope
|
Activity
|
ActivityComponent
|
@ActivityScoped
|
Fragment
|
FragmentComponent
|
@FragmentScoped
|
View
|
ViewComponent
|
@ViewScoped
|
带有 @WithFragmentBindings 注释的 View
|
ViewWithFragmentComponent
|
@ViewScoped
|
Service
|
ServiceComponent
|
@ServiceScoped
|
默认情况下,Hilt 中的所有绑定都未限定作用域。这意味着,每当应用请求绑定时,Hilt 都会创建所需类型的一个新实例。
若限定作用域,如:
@ActivityScoped
class AnalyticsAdapter @Inject constructor(private val service: AnalyticsService
) { ... }
@ActivityScoped: Hilt 会在相应 Activity 的整个生命周期内提供 AnalyticsAdapter
的同一实例.
组件层次结构
父组件中绑定的依赖项,对子组件是可见的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xCeJBtzE-1604903187718)(https://developer.android.google.cn/images/training/dependency-injection/hilt-hierarchy.svg)]
注意:默认情况下,如果您在视图中执行字段注入,
ViewComponent
可以使用ActivityComponent
中定义的绑定。如果您还需要使用FragmentComponent
中定义的绑定并且视图是 Fragment 的一部分,应将@WithFragmentBindings
注释和@AndroidEntryPoint
一起使用。
在 Hilt 不默认支持的类中注入依赖项
@EntryPoint 创建入口点。
ContentProvider 不能直接使用 @AndroidEntryPoint ; BroadcastReceiver 也不能。
class ExampleContentProvider : ContentProvider() {@EntryPoint@InstallIn(ApplicationComponent::class)interface ExampleContentProviderEntryPoint {fun analyticsService(): AnalyticsService}...
}
实例:普通类注入 不同的Retrofit(不同的baseUrl) 对象
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface FleetRetrofitProviderEntryPoint {@FleetRetrofitfun getFleetRetrofit(): Retrofit//再定义一个不同的 Retrofit baseUrl 的 对象获取函数,不同的 Qualifier
}{//val appContext = ExpressApplication.instance().applicationContext?: throw IllegalStateException()val networkModule = EntryPointAccessors.fromApplication(appContext, FleetRetrofitProviderEntryPoint::class.java)val retrofit = networkModule.getFleetRetrofit() //获取相应的Retrofitval result = retrofit.create(LoginService::class.java).m()...
}
详情见 fleet项目中的 NetworkModule, LoginBiz
实例:普通类 注入 Repository
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface LocationReceiverEntryPoint {fun repository(): LocationUploadRepository
}{val entry = EntryPointAccessors.fromApplication(ExpressApplication.instance().applicationContext, LocationReceiverEntryPoint::class.java)val result = entry.repository().updateLocation(LocationUploadBody(locationItems))
}
详情见 fleet项目中的 LocationUpdatesBroadcastReceiver
使用 Hilt 注入 ViewModel 对象
app/build.gradle
dependencies {...implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'// When using Kotlin.kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'// When using Java.annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
}
在 ViewModel
对象的构造函数中使用 @ViewModelInject
注释来提供一个 ViewModel
。您还必须使用 @Assisted
为 SavedStateHandle
依赖项添加注释:
class ExampleViewModel @ViewModelInject constructor(private val repository: ExampleRepository,@Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {...
}
然后,带有 @AndroidEntryPoint
注释的 Activity 或 Fragment 可以使用 ViewModelProvider
或 by viewModels()
KTX 扩展 照常获取 ViewModel
实例:
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {private val exampleViewModel: ExampleViewModel by viewModels() //or activityViewModels()...
}
androidx.lifecycle.SavedStateHandle 用于 Activity/Fragment重建时保存变量用的。
- getLiveData(key, [v]): MutableLiveData 获取不到,会内部创建 LiveData; 一个key对应一个LiveData,存放在一个 Map<String, LiveData>中。
- keys(): Set
- set(key, v) 从map中,若取得 LiveData,则liveData.setValue(); 若取不得则存放在 一个Map<String, Object> 中。
- get(key) 从Map<String, Object> 中 get(key)。
使用 Hilt 注入 WorkManager
app/build.gradle
dependencies {...implementation 'androidx.hilt:hilt-work:1.0.0-alpha01'// When using Kotlin.kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'// When using Java.annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
}
在 Worker
对象的构造函数中使用 @WorkerInject
注释来注入一个 Worker
。您只能在 Worker
对象中使用 @Singleton
或未限定作用域的绑定。您还必须使用 @Assisted
为 Context
和 WorkerParameters
依赖项添加注释:
class ExampleWorker @WorkerInject constructor(@Assisted appContext: Context,@Assisted workerParams: WorkerParameters,workerDependency: WorkerDependency
) : Worker(appContext, workerParams) { ... }
然后,让 Application
类实现 Configuration.Provider
接口,注入 HiltWorkFactory
的实例,并将其传入 WorkManager
配置:
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {@Inject lateinit var workerFactory: HiltWorkerFactoryoverride fun getWorkManagerConfiguration() =Configuration.Builder().setWorkerFactory(workerFactory).build()
}
Android Dagger-Hilt 依赖注入相关推荐
- android组件浮动在activity上_Jetpack Hilt 依赖注入框架上手指南
code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:LvKang-insist 链接:https://juejin.im/post/5efdff9d6fb9a07e ...
- Android hilt 依赖注入使用详解
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/128424833 本文出自[赵彦军的博客] 文章目录 官方文档 作用域于树图 添加依 ...
- [Android]使用Dagger 2依赖注入 - DI介绍(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5092083.html 使用Dagger 2依赖注入 - DI介 ...
- [Android]使用Dagger 2依赖注入 - 自定义Scope(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5095426.html 使用Dagger 2依赖注入 - 自定义 ...
- 具有Hilt的Android上的依赖注入
重点 (Top highlight) Dependency injection (DI) is a technique widely used in programming and well suit ...
- Android开源框架——依赖注入Dagger
介绍:Dagger是Square公司开发依赖注入框架,主要针对辅助类对象,而ButterKnife是针对View视图对象的. github:https://github.com/square/dagg ...
- Android开发中依赖注入的应用
什么是依赖注入? 依赖是指一个对象持有其他对象的引用.依赖注入则是将这些依赖对象传递给被依赖对象,而不是被依赖对象自己创建这些对象. public class MyClass{private Ano ...
- Android开源框架——依赖注入ButterKnife
若对依赖注入不熟悉,请阅读博客中的另外一篇IOC控制反转浅析 介绍:ButterKnife是Square公司员工JakeWharton开发的一款针对View视图对象的依赖注入库.目的是通过依赖注入方式 ...
- Android 依赖注入可以更简单 —— 新版本 Dagger 2 使用教学
今年 3 月 21 号 Dagger 2 在 2.10 版本之后针对 Android 方面做了很大的优化,使用方法也随之有了不少变化.本次改动除了让 Dagger 2 的使用更加符合控制反转原则,还针 ...
- [Android]使用Dagger 2进行依赖注入 - Producers(翻译)
使用Dagger 2进行依赖注入 - Producers 原文:http://frogermcs.github.io/dependency-injection-with-dagger-2-produc ...
最新文章
- NanoPi NEO Air使用十一:编写SPI驱动点亮TFT屏幕,ST7789V
- Python词云 wordcloud 十五分钟入门与进阶
- 新安装和已安装nginx如何添加未编译安装模块/补丁
- 【struts2】struts2配置文件—struts.properties
- c语言大作业旋转,c语言大作业全-20210412035629.docx-原创力文档
- C语言之常见错误解决办法
- lodop转到其他html页面,Lodop实现打印功能
- mv强制覆盖 shell_生产力工具:shell 与 Bash 脚本
- python 列表有没有顺序_python-如何获取列表的所有顺序,以使该列表等于另一个列表?...
- Jenkins 新版本及插件在Windows下的安装
- 在KVM虚拟机中使用spice系列之二(USB映射,SSL,密码,多客户端支持)
- 收集的一些discuz插件常用插件分享给大家了
- windows xp sp3(XP3)无法安装或使用iis的根本原因及解决办法研究
- 341编程器 软硬件
- 【神经网络】综合篇——人工神经网络、卷积神经网络、循环神经网络、生成对抗网络
- microsoftstore连不上网_修复Microsoft Store 无法连接网络 代码: 0x80072EFD
- 已知三角形的三条边长,求这个三角形的外接圆的半径
- 银河土星_设计师来自土星,开发人员来自木星:或者,为什么沟通很重要
- 代码防御性编程的十条技巧
- 华为手机无法安装ADB和HDB的处理