Hilt依赖注入详解与实战教程 – 基于tdxtxt/blog项目

引入Hilt

  • 在项目根目录的build.gradle文件中配置Hilt的插件路径
classpath  com.google.dagger:hilt-android-gradle-plugin:2.28-alpha  
  • 在app/build.gradle文件中,引入Hilt的插件并添加Hilt的依赖库
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:2.28-alpha"
    kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}

简单使用

  • 在Application类上添加注解 @HiltAndroidApp
@HiltAndroidApp
class MyApplication : Application() {
   ...
}
  • 在需要引入的地方(Activity、Fragment、View)添加注解 @androidentrypoint,同时需要在注解的对象添加 @Inject
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {
    @Inject
    var bean: Bean
     ...
}
  • 在需要注入的对象构造方法上添加注解 @Inject
class Bean @Inject constructor() {
    ...
}

带参数的依赖注入

  • 在需要注入的对象构造方法上添加注解,同时构造方法中传入参数
class Bean @Inject constructor(val subBean: SubBean) {
    ...
}
  1. 若参数对象为普通对象时,直接在其构造方法上添加@Inject对象
class SubBean @Inject constructor() {
    ...
}
  1. 若参数对象为接口类型时,请参考【接口的依赖注入】
  2. 若参数对象为第三方类类型时,请参考如下【第三方类的依赖注入】

接口的依赖注入

  • 实现接口类
interface Repository {
    ...
}
class NetRepository @Inject constructor() : Repository {
    ...
}
class LocalRepository @Inject constructor() : Repository {
    ...
}
  • 定义注解(该步骤主要用来标记注入不同实现接口的实例)
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindNetRepository
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindLocalRepository 
  • 添加Module
@Module
@InstallIn(ApplicationComponent::class)
abstract class ModuleImpl {
    @BindNetRepository
    @Binds
    abstract fun bindRepository1(repository: NetRepository): Repository

    @BindLocalRepository 
    @Binds
    abstract fun bindRepository2(repository: LocalRepository): Repository
}
  • 引入接口实现类
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {
    @BindNetRepository
    @Inject
    var repository1: Repository

    @BindLocalRepository 
    @Inject
    var repository2: Repository
     ...
}

第三方类的依赖注入

  • 添加Module
@Module
@InstallIn(ApplicationComponent::class)
class ModuleNetwork {
    @Singleton //该注解表明全局单例
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(20, TimeUnit.SECONDS)
            .readTimeout(20, TimeUnit.SECONDS)
            .writeTimeout(20, TimeUnit.SECONDS)
            .build()
    }
    @Singleton //该注解表明全局单例
    @Provides
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl("https://xxxx.com/")
            .client(okHttpClient)
            .build()
    }
}
  • 引入三方实体类
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {
    @Inject
    lateinit var retrofit: Retrofit
    ...
}

注入Context对象

  • ApplicationContext获取
@Module
@InstallIn(ApplicationComponent::class)
class ApplicationModule {
    @Provides
    fun provideCustomApplication(application: Application): CustomApplication {
        return application as CustomApplication
    }
}
@Singleton
class Presenter @Inject constructor(@ApplicationContext val context: Context) {
}
///////////////////////////////或者///////////////////////////////////////////
@Singleton //小技巧,这里可以去掉@ApplicationContext 注解,但必须使用Application参数类型
class Presenter @Inject constructor(val context: Application) {
}
///////////////////////////////或者///////////////////////////////////////////
@Singleton
class Presenter @Inject constructor(val context: CustomApplication) {
}
  • ActivityContext获取
// 这里必定不要使用@Singleton注解
class Presenter @Inject constructor(@ActivityContext val context: Context) {
}
///////////////////////////////或者///////////////////////////////////////////
//小技巧,这里可以去掉@ActivityContext 注解,但必须使用Activity参数类型
class Presenter @Inject constructor(val activity: Activity) {
}

Hilt内置主键与作用域

  • 在添加Module类时,使用的@Installin注解需要传入一个组件类型,表明注入到该组件中,支持组件如下图,这张表中,每个组件的作用范围都不一样,其中ApplicationComponent组件提供的依赖注入实例可以在全项目中使用。我们不必非得在某个Module中使用作用域注解,也可以直接将它声明到任何可注入类的上方。列如我们对Bean类进行如下声明
@Module
@InstallIn(ApplicationComponent::class)
class ModuleNetwork {
    @Singleton //该注解表明全局单例
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(20, TimeUnit.SECONDS)
            .readTimeout(20, TimeUnit.SECONDS)
            .writeTimeout(20, TimeUnit.SECONDS)
            .build()
    }
}
@Singleton
class Bean @Inject constructor() {
    ...
}

hilt_1
hilt_2

ViewModel的依赖注入

  • 普通注入方式(缺点:改变了获取ViewModel实例的常规方式)
class Repository @Inject constructor() {
    ...
}
@ActivityRetainedScoped
class HomeViewModel @Inject constructor(val repository: Repository) : ViewModel() {
    ...
}
@AndroidEntryPoint
class HomeActivity : AppCompatActivity() {
    @Inject
    lateinit var viewModel: HomeViewModel 
    ...    
}
  • 特殊注入方式
//引入插件
dependencies {
    ...
    implementation  androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02 
    kapt  androidx.hilt:hilt-compiler:1.0.0-alpha02 
}
class HomeViewModel @ViewModelInject constructor(val repository: Repository) : ViewModel() {
    ...
}
@AndroidEntryPoint
class HomeActivity : AppCompatActivity() {
    val viewModel: HomeViewModel by lazy { ViewModelProvider(this).get(HomeViewModel ::class.java) }
    ...
}

官网教程

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容