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
) { ... }

在本例中,AnalyticsServiceAnalyticsAdapter 的一个依赖项。因此,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。您还必须使用 @AssistedSavedStateHandle 依赖项添加注释:

class ExampleViewModel @ViewModelInject constructor(private val repository: ExampleRepository,@Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {...
}

然后,带有 @AndroidEntryPoint 注释的 Activity 或 Fragment 可以使用 ViewModelProviderby 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 或未限定作用域的绑定。您还必须使用 @AssistedContextWorkerParameters 依赖项添加注释:

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 依赖注入相关推荐

  1. android组件浮动在activity上_Jetpack Hilt 依赖注入框架上手指南

    code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:LvKang-insist 链接:https://juejin.im/post/5efdff9d6fb9a07e ...

  2. Android hilt 依赖注入使用详解

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/128424833 本文出自[赵彦军的博客] 文章目录 官方文档 作用域于树图 添加依 ...

  3. [Android]使用Dagger 2依赖注入 - DI介绍(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5092083.html 使用Dagger 2依赖注入 - DI介 ...

  4. [Android]使用Dagger 2依赖注入 - 自定义Scope(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5095426.html 使用Dagger 2依赖注入 - 自定义 ...

  5. 具有Hilt的Android上的依赖注入

    重点 (Top highlight) Dependency injection (DI) is a technique widely used in programming and well suit ...

  6. Android开源框架——依赖注入Dagger

    介绍:Dagger是Square公司开发依赖注入框架,主要针对辅助类对象,而ButterKnife是针对View视图对象的. github:https://github.com/square/dagg ...

  7. Android开发中依赖注入的应用

    什么是依赖注入? 依赖是指一个对象持有其他对象的引用.依赖注入则是将这些依赖对象传递给被依赖对象,而不是被依赖对象自己创建这些对象.  public class MyClass{private Ano ...

  8. Android开源框架——依赖注入ButterKnife

    若对依赖注入不熟悉,请阅读博客中的另外一篇IOC控制反转浅析 介绍:ButterKnife是Square公司员工JakeWharton开发的一款针对View视图对象的依赖注入库.目的是通过依赖注入方式 ...

  9. Android 依赖注入可以更简单 —— 新版本 Dagger 2 使用教学

    今年 3 月 21 号 Dagger 2 在 2.10 版本之后针对 Android 方面做了很大的优化,使用方法也随之有了不少变化.本次改动除了让 Dagger 2 的使用更加符合控制反转原则,还针 ...

  10. [Android]使用Dagger 2进行依赖注入 - Producers(翻译)

    使用Dagger 2进行依赖注入 - Producers 原文:http://frogermcs.github.io/dependency-injection-with-dagger-2-produc ...

最新文章

  1. 使用U-Nets和深度学习进行自动缺陷检查
  2. android倒计时功能,Android 实现列表倒计时功能
  3. VTK:图片之ImageValueRange
  4. 上传jar包到nexus私服
  5. Linux中后台执行scp
  6. MGraph图(代码、分析、汇编)
  7. stm32c语言设计以及注释,13个基于STM32的经典项目设计实例,全套资料~-嵌入式系统-与非网...
  8. LeetCode 629. K个逆序对数组(DP)
  9. wget下载一个目录下的文件
  10. 为系统扩展而采取的一些措施——缓存
  11. javascript将内嵌式广告隐藏
  12. 疑似小米10超大杯入网:搭载骁龙865+/120Hz高刷屏加持
  13. 流程控制: jQ Deferred 与 ES6 Promise 使用新手向入坑!
  14. windows c语言 sata 序列号,【Delphi】获取IDE/SATA硬盘序列号
  15. HTTP 压力测试工具 wrk和ab
  16. 【洛谷 2888】牛栏
  17. 前端配色方案:最舒服的十种颜色
  18. 孙正义与马云的故事:马云就是他心目中的那个人
  19. lange耦合器设计步骤_用于承受1000W的3dBLange耦合器及制备方法与流程
  20. OpenSSL下载安装教程

热门文章

  1. 怎么查看html格式的文件在哪里,网页缓存文件在哪里?如何查看网页缓存文件?...
  2. 这款开源 IDE 性能傲视 VS Code,值得尝试一下
  3. Python算法设计 - McCarthy 91
  4. 修改MojoWeixin 只保留用户name 取消群昵称
  5. Chanel收购200多年历史的西班牙皮革制造商 Colomer
  6. pythonzeros函数_Python numpy.zeros函数方法的使用
  7. cad在线转换_还不知道CAD怎么转PDF?新同事教我这简单到不行的三招,招招强大...
  8. JVM内存区域划分Eden Space\Survivor Space\Tenured Gen\Perm Gen
  9. 基础篇:独占锁、共享锁、公平锁、非公平锁,叫我如何分得清
  10. Python--ndarray 常用属性详解