Jetpack系列(七) — Hilt
Hilt 简单介绍
初步印象
Hilt 是专为 Android 设计的依赖项注入库,可减少在项目中手动创建实例
Hilt 通过为项目中的每个 Android 类提供容器并自动为您管理其生命周期,定义了一种在应用中执行 DI 的标准方法
Hilt 在热门 DI 库
Dagger
的基础上构建而成,因而能够受益于 Dagger 提供的编译时正确性、运行时性能、可伸缩性和 Android Studio 支持。
基本概念
依赖项注入:以参数形式提供所需的对象,应用可以在构造类时提供这些依赖项,或者将这些依赖项传入需要各个依赖项的函数
- 构造函数注入
- 字段注入(或 setter 注入)
// 方式一: 构造函数注入 class Car(private val engine: Engine) { fun start() { engine.start() } } // 方式二: 字段注入 class Car { lateinit var engine: Engine fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.engine = Engine() car.start() } 复制代码
依赖项容器类
- 容器类中实现类的创建,类似于
Spring
框架中的效果
Hilt 目前支持以下 Android 类
Application
(通过使用@HiltAndroidApp
)Activity
Fragment
View
Service
BroadcastReceiver
Hilt 基本使用
简单注入
-
@HiltAndroidApp
注释的Application
类// BaseApplication.kt @HiltAndroidApp class BaseApplication : Application() 复制代码
-
@AndroidEntryPoint
注释的其他 Android 类提供依赖项- 如果您使用
@AndroidEntryPoint
为某个Android
类添加注释,则还必须为依赖于该类的Android
类添加注释。例如,如果您为某个Fragment
添加注释,则还必须为使用该Fragment
的所有Activity
添加注释。
// MainActivity... @AndroidEntryPoint class MainActivity : AppCompatActivity() {} 复制代码
- 如果您使用
-
应用和定义Hilt 绑定
@Inject
成员对象引入@Inject
构造函数注入
// 官方代码 @AndroidEntryPoint class ExampleActivity : AppCompatActivity() { // `@Inject` 成员对象引入 @Inject lateinit var analytics: AnalyticsAdapter ... } class AnalyticsAdapter @Inject constructor() { ... } 复制代码
注入viewmodel
-
创建
ViewModel
- 我用的
hilt
是2.35
版本,直接@HiltViewModel
,老版本可以使用@ViewModelInject
@HiltViewModel class HomeViewModel @Inject constructor() : ViewModel() {} 复制代码
- 我用的
-
引用
ViewModel
// HomeFragment.kt private val viewModel: HomeViewModel by viewModels() 复制代码
-
ViewModel
中有参数的情况@Inject
构造函数注入
// MainViewModel.kt @HiltViewModel class MainViewModel @Inject constructor( private val repository: WordRepository ) : ViewModel() {...} // WordRepository.kt class WordRepository @Inject constructor( private val wordDao: WordDao ) {...} 复制代码
相关知识点
知识点一:Hilt 模块
-
类型不能通过构造函数注入,可使用模块
-
使用
@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 { @Binds abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl ): AnalyticsService } 复制代码
-
使用
@Provides
注入实例,通常是外部库、或者必须使用构建器模式创建实例// 官网代码 @Module @InstallIn(ActivityComponent::class) object AnalyticsModule { @Provides fun provideAnalyticsService( // Potential dependencies of this type ): AnalyticsService { return Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService::class.java) } } 复制代码
知识点二: 同一类型个绑定
-
Hilt 以依赖项的形式提供同一类型的不同实现,可以使用
@Qualifier
限定符为实现// 官方代码 @Qualifier annotation class InMemoryLogger @Qualifier annotation class DatabaseLogger @InstallIn(SingletonComponent::class) @Module abstract class LoggingDatabaseModule { @DatabaseLogger @Singleton @Binds abstract fun bindDatabaseLogger(impl: LoggerLocalDataSource): LoggerDataSource } @InstallIn(ActivityComponent::class) @Module abstract class LoggingInMemoryModule { @InMemoryLogger @ActivityScoped @Binds abstract fun bindInMemoryLogger(impl: LoggerInMemoryDataSource): LoggerDataSource } 复制代码
知识点三: 使用
@EntryPoint
注释创建入口点
-
需要在 Hilt 不支持的类中执行字段注入,比如
ContentProvider
,可以使用@EntryPoint
注释创建入口点// 官方代码 class LogsContentProvider: ContentProvider() { @InstallIn(SingletonComponent::class) @EntryPoint interface LogsContentProviderEntryPoint { fun logDao(): LogDao } ... private fun getLogDao(appContext: Context): LogDao { val hiltEntryPoint = EntryPointAccessors.fromApplication( appContext, LogsContentProviderEntryPoint::class.java ) return hiltEntryPoint.logDao() } } 复制代码
相关链接
参考资料
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END