day1 Hilt
一:开始
在https://dagger.dev/hilt/gradle-setup中找到依赖
二:写一个Application
- 写一个类继承系统的Application,
- 并把它写在Manifest里,
- 并加上注释:@HiltAndroidApp
例子:
/** * 使用hilt需要加这个注释 */ @HiltAndroidApp class MyApplication: Application() { }
三:写Module
Module的作用是定义要注入的东西,比如Room实例,Retrofit实例。Module包含以下几个部分:
- Module的注释:表示Module里面的依赖是全局不变的,亦或随Activity变化的,亦或随Fragment变化的......
比如:SingletonComponent/ActivityComponent/FragmentComponent/ViewModelComponent
- 若干个方法:表示要提供的依赖。方法也有注释,例如
@Sington/@ActiviytScoped/@FragmentScoped
方法上的范围注释:
说一些注意事项:
- 假如Module使用的是@SingletonComponent注释,那么方法,要么是@Singleton注释,要么不加注释,第一种情况的效果是:注入的方法只会执行一次
@Singleton @Provides @Named("string5") fun provideOneString5():String { log("执行provideOneString5") // log只会执行一次 return 一个string }
- 假如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 { } }
帮助性的注释:
- @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() }
- 在方法的参数上加上@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
- @ViewModelInject已经废弃了
- 官方的文档有挺多错误,完整的依赖应该是:
// 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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步