Jetpack Hilt总结

Jetpack Hilt

概述

  • 依赖注入指Dependency Injection,简称DI,Hilt是一个功能强大用法简单的依赖注入框架
  • 依赖注入有利于代码节藕

官方文档

配置

项目根目录build.gradle

buildscript {
    
    
    ext {
    
    
        hiltVersion = "2.36"
    }
    dependencies {
    
    
        //Hilt
        classpath "com.google.dagger:hilt-android-gradle-plugin:$hiltVersion"
    }
}

模块目录build.gradle

apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

android {
    
    
    compileOptions {
    
    
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}


dependencies {
    
    
    implementation "com.google.dagger:hilt-android:$hiltVersion"
    kapt "com.google.dagger:hilt-android-compiler:$hiltVersion"
}

API介绍

支持入口点

  • Application 使用@HiltAndroidApp
  • ViewModel 使用@HiltViewModel
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

说明:其他入口点使用@AndroidEntryPoint注解

内置Hilt组件

@InstallIn(ActivityComponent::class) 表示将这个模块安装到Activity组件中。

@InstallIn(ApplicationComponent::class)可以将视力放在全项目中使用。

Hilt组件 注入的对象
SingletonComponent Application
ActivityRetainedComponent N/A
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent 带有@WithFragmentBindings注释的View
ServiceFragment Service

组件生命周期

Hilt会按照响应Android类的生命周期自动创建和销毁生成的组件类的实例。

Hilt组件 创建时机 销毁时机
SingletonComponent Application#onCreate() Application@onDestroy()
ActivityRetainedComponent Activity#onCreate() Activity#onDestroy()
ViewModelComponent ViewModel被创建 ViewModel被销毁
ActivityComponent Activity#onCreate() Activity#onDestroy()
FragmentComponent Fragment#onAttach() Fragment#onDestroy()
ViewComponent View#super() 视图被销毁
ViewWithFragmentComponent View#super() 视图被销毁
ServiceComponent Service#onCreate() Service#onDestroy()

组件作用域

每当应用请求绑定时,Hilt都会创建所需类型的一个新实例。

Hilt允许将绑定的作用域限定为特定组件。Hilt只为绑定作用域限定到的组件的每个实例创建一次限定作用域的绑定,对该绑定的所有请求共享同一实例。

如:@Singleton表示全局单例,@ActivityScoped表示在同一Activity范围内共享一个实例。

Hilt组件 Android类 作用域
SingletonComponent Application @Singleton
ActivityRetainedComponent Activity @ActivityRetainedScoped
ViewModelComponent ViewModel @ViewModelScoped
ActivityComponent Activity @ActivityScoped
FragmentComponent Fragment @FragmentScoped
ViewComponent View @ViewScoped
ViewWithFragmentComponent 带有@WithFragmentBindings注释的View @ViewScoped
ServiceComponent Service @ServiceScoped

组件层次结构

对某个类声明了某种作用域注解之后,这个注解的箭头所能指到的地方,都可以对该类进行依赖注入,同时在该范围内共享同一个实例。

在这里插入图片描述

基本使用

配置Application

在Hilt中,必须定义一个Application,使用@HiltAndroidApp注解

@HiltAndroidApp
class BaseApp : Application() {
    
    
}

基本注入

  • 使用@AndroidEntryPoint注解定义Activity为注入点
  • 使用@Inject注解在user字段上,表示通过Hilt注入
  • User类的构造函数上声明@Inject注解,表示通过构造函数创建一个对象
  • 使用@Inject注解的字段不能为private
class User @Inject constructor(){
    
    
}

使用

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    
    

    @Inject
    lateinit var user: User

    @Inject
    lateinit var user2: User

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        log("$user") //com.example.hiltdemo.User@d4f5027
        log("$user2") //com.example.hiltdemo.User@a5b32d4
    }
}

带参数的注入

  • 在Car类的构造函数里新增一个参数
class Car @Inject constructor(val user: User) {
    
    
    fun drive() {
    
    
        log("$user 正在开车") 
    }
}

使用

@Inject
lateinit var car: Car

car.drive() //User@77b6f83 正在开车

接口对象的注入

  • 定义一个Engine接口
  • 实现两个类GasEngine、ElectricEngine
  • 定义一个模块类EngineModule,使用@Binds注解提供依赖注入的对象
interface Engine {
    
    
    fun start()
    fun shutdown()
}
class GasEngine @Inject constructor() : Engine {
    
    
    override fun start() {
    
    
        log("燃油引擎 start")
    }

    override fun shutdown() {
    
    
        log("燃油引擎 shutdown")
    }
}

class ElectricEngine @Inject constructor() : Engine {
    
    
    override fun start() {
    
    
        log("电力引擎 start")
    }

    override fun shutdown() {
    
    
        log("电力引擎 shutdown")
    }
}
@Module
@InstallIn(ActivityComponent::class)
abstract class EngineModule {
    
    

    @Binds
    abstract fun bindEngine(gasEngine: GasEngine): Engine
}

使用

class Car @Inject constructor(val user: User) {
    
    

    @Inject
    lateinit var engine: Engine

    fun drive() {
    
    
        engine.start()
        log("$user 正在开车")
        engine.shutdown()
    }
}

相同类型注入不同的对象

  • 使用@Qualifier注解分别定义2个注解:BindGasEngine、BindElectricEngine
  • 定义一个Module类,分别添加2个注解
  • 在注入的地方使用2个注解
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindGasEngine

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindElectricEngine
@Module
@InstallIn(ActivityComponent::class)
abstract class SelectEngineModule {
    
    

    @BindGasEngine
    @Binds
    abstract fun bindGasEngine(gasEngine: GasEngine): Engine

    @BindElectricEngine
    @Binds
    abstract fun bindElectricEngine(electricEngine: ElectricEngine): Engine
}

使用

class Car @Inject constructor(val user: User) {
    
    
    @BindGasEngine
    @Inject
    lateinit var gasEngine: Engine

    @BindElectricEngine
    @Inject
    lateinit var electricEngine: Engine
}

对象的注入

  • 定义一个模块类
  • 使用@Provides注解提供对象
@Module
@InstallIn(SingletonComponent::class)
class NetworkModule {
    
    

    @Singleton
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
    
    
        return OkHttpClient.Builder()
        .build()
    }

    @Singleton
    @Provides
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
    
    
        return Retrofit.Builder()
        .baseUrl("https://wanandroid.com/")
        .build()
    }
}

使用

@Inject
lateinit var okHttpClient: OkHttpClient

@Inject
lateinit var retrofit: Retrofit

Application & Context

Hilt提供了@ApplicationContext@ActivityContext内置注解,会自动提供一个Application类型和Activity类型的Context传入

class MyContext @Inject constructor(
    @ApplicationContext val conext: Context,
    @ActivityContext val activityContext: Context
) 
@Inject
lateinit var myContext: MyContext

log("myContext : ${
      
      myContext.conext}  ${
      
      myContext.activityContext}")

组件的默认绑定

每个Hilt组件都默认绑定的对象,如:在ActivityComponent组件中,默认绑定Application/Activity

class MyContext2 @Inject constructor(
    val application: Application,
    val activity: Activity
) 
@Inject
lateinit var myContext2:

log("myContext2 : ${
      
      myContext2.application} ${
      
      myContext2.activity}")

ViewModel的依赖注入

  • MVVM架构中,仓库层的实例应该由ViewModel层创建
  • ViewModel层需要使用@ActivityRetainedScoped注解,在ViewModel的构造函数里添加仓库层的依赖

仓库层

class Repository @Inject constructor() {
    
    

    fun getData() = "从仓库获取了数据"
}

ViewModel层

@HiltViewModel
class MyViewModel @Inject constructor(
    private val savedStateHandle: SavedStateHandle,
    private val repository: Repository
) : ViewModel() {
    
    

    private val liveData = MutableLiveData<String>()

    fun loadData(): MutableLiveData<String> {
    
    
        viewModelScope.launch {
    
    
            delay(5000L)
            liveData.value = repository.getData()
        }
        return liveData
    }
}

View层

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    
    

    private val viewModel by viewModels<MyViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel.loadData().observe(this) {
    
    
            log(it)
        }
    }
}

代码下载

猜你喜欢

转载自blog.csdn.net/qq_14876133/article/details/119082018