you are bes|

ou尼酱~~~

园龄:4年10个月粉丝:1关注:0

day1 Hilt

一:开始

在https://dagger.dev/hilt/gradle-setup中找到依赖

 

二:写一个Application

  1. 写一个类继承系统的Application,
  2. 并把它写在Manifest里,
  3. 并加上注释:@HiltAndroidApp

例子:

/**
 * 使用hilt需要加这个注释
 */
@HiltAndroidApp
class MyApplication: Application() {
}

 

三:写Module

Module的作用是定义要注入的东西,比如Room实例,Retrofit实例。Module包含以下几个部分:

  1. Module的注释:表示Module里面的依赖是全局不变的,亦或随Activity变化的,亦或随Fragment变化的......
    比如:SingletonComponent/ActivityComponent/FragmentComponent/ViewModelComponent
  2. 若干个方法:表示要提供的依赖。方法也有注释,例如
    @Sington/@ActiviytScoped/@FragmentScoped

     

方法上的范围注释:

说一些注意事项:

  1. 假如Module使用的是@SingletonComponent注释,那么方法,要么是@Singleton注释,要么不加注释,第一种情况的效果是:注入的方法只会执行一次
    @Singleton
        @Provides
        @Named("string5")
        fun provideOneString5():String {
            log("执行provideOneString5") // log只会执行一次
            return 一个string
        }

     

    第二种情况的效果是,需要inject都会执行一次。
  2. 假如Module使用的是@ActivityComponent注释,那么方法,要么是@ActivityScoped注释,要么不加注释,第一种情况的效果是,注入的方法在一个activity的生命周期只会执行一次,切到其他activity会再次执行获取新实例。第二种情况效果是,需要inject都会执行,跟第一点一样。

总而言之,Module关于@InstallIn()的注释和方法上的范围注释有一个约束关系。

必须的注释:

例如:

复制代码
@Module  这是一个必须的注释
@InstallIn(SingletonComponent::class)这是一个必须的注释,参数可选
object AppModule {

    val hardString = String(CharArray(5) {
        'h'
    })

    @Singleton可选,两种选择,参照上一节
    @Provides这是一个必须的注释,表示这个方法提供依赖
    @Named("string1")可选,但是最好加上,识别要注入的依赖
    fun provideOneString() = 

    @Singleton
    @Provides
    @Named("string2")
    fun provideOneString2() = 

    @Singleton
    @Provides
    @Named("string5")
    fun provideOneString5():String {
        
    }
}
复制代码

 

帮助性的注释:

  1. @ApplicationContext,在方法中提供Context上下文
       @Singleton
        @Provides
        @Named("string6")
        fun provideOneString6(@ApplicationContext context: Context):String {
            return context.getString(R.string.xxx)
        }

     有更简便的写法:

    复制代码
    @Provides
        @Singleton
        fun provideStockDatabase(app: Application): StockDatabase {
            return Room.databaseBuilder(
                app,
                StockDatabase::class.java,
                "stockdb.db"
            ).build()
        }
    复制代码

     

  2. 在方法的参数上加上@Named,表示依赖需要module中的其他依赖
    @Singleton
        @Provides
        @Named("string7")
        fun provideOneString7(@Named("string2") otherString: String):String {
            return "$otherString  before me is otherString."
        }

     

心得体会

一般来说,在SingletonComponent里面注释都乖乖加上@Singleton表示全局唯一,在ActivityComponent里面也乖乖加上@ActivityScoped表示注入的依赖的生命周期跟随activity。一般不会用到我上面说的不写范围约束注释的情况(名字自己起的),如果每次都创建那为什么不自己创建?要写依赖注入呢?doge

一般来说,还是全局的依赖注入用的比较多,如果要随activity之类的我完全可以把实例写在activity里,或者viewmodel里(这才mvvm)。

 

四:需要注入的地方

这就比较简单了:

1:

/**
     * wrong: Dagger does not support injection into private fields
     *
     * name和AppModule中的一一对应
     */
    @Inject
    @Named("string1")
    lateinit var injectString1: String

 2:

在activity或fragment中加上

复制代码
/**
 * 需要注入,加这个注释。可以加的类看[AndroidEntryPoint]的注释。
 *
 * fragment要加的话,它的activity也要加
 */
@AndroidEntryPoint
class HiltActivity: ComponentActivity() {

}
复制代码

 viewmodel特殊一点:

可以参考:https://developer.android.com/training/dependency-injection/hilt-jetpack

  1. @ViewModelInject已经废弃了
  2. 官方的文档有挺多错误,完整的依赖应该是:
    复制代码
        // hilt
        implementation 'com.google.dagger:hilt-android:2.41'
        kapt 'com.google.dagger:hilt-compiler:2.41'
        // When using Kotlin.
        kapt 'androidx.hilt:hilt-compiler:1.0.0'
        implementation 'androidx.activity:activity-ktx:1.4.0'
    
    
        id 'kotlin-kapt'
        id 'dagger.hilt.android.plugin'
    
    
    
    ——————————————————
    buildscript {
     
        dependencies {
            classpath 'com.google.dagger:hilt-android-gradle-plugin:2.41'
        }
    }
    复制代码

    要删除implementation 'androidx.hilt:hilt-lifecycle-viewmodel:x.x.x',不然在viewmodel的使用中会报错,目前用法

    复制代码
    @HiltViewModel
    class HiltViewModel @Inject constructor(@Named("string1") string1: String):ViewModel() {
    //    @Inject
    //    @Named("string1")
    //    lateinit var injectString1: String
        init {
    //        log("$injectString1")  error
            log(string1)
        }
    }
    复制代码

     

 

本文作者:ou尼酱~~~

本文链接:https://www.cnblogs.com/--here--gold--you--want/p/16114388.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ou尼酱~~~  阅读(76)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起