1 依赖注入
什么是依赖注入,就是在一个类中,经常依赖另一个类,需要使用这个类的方法或者字段,那么想要使用这个类,就需要创建这个类的实例,如果依赖的类多,那么就需要创建很多实例,这是非常消耗资源的方式,那么如果你非常熟悉设计模式,那么可以使用手动依赖注入的方式,或者参数注入的方式
interface Engine{
fun doWork()
}
class Factory(private val engine: Engine){
fun doSomething(){
engine.doWork()
}
}
class AEngine : Engine{
override fun doWork() {
println("这是A引擎")
}
}
class BEngine : Engine{
override fun doWork() {
println("这是B引擎")
}
}
如果想要生产A引擎,那么就传入A引擎的实例,如果想要生产B引擎,那么就可以传入B引擎的实例,这就是简单的手动依赖注入,那么这种方式存在什么不足吗?
var factory = Factory(AEngine())
factory.doSomething()
在一个项目中,可能不止一个地方在用这个工厂方法,那么就需要在任何使用的地方写这些模板代码,而且在使用Factory之前,必须要把所有的依赖项的实例创建出来。
2 Hilt依赖注入
对于Hilt的依赖注入,主要是在JectPack组件中使用。在此之前,Dagger是依赖注入的常客,但是其使用难度比较大,因此Google在Dagger的基础上,推出了Hilt组件,用于解决大量模板代码的构建。
2.1 依赖配置
app build.gradle
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
plugins
id 'dagger.hilt.android.plugin'
id 'kotlin-kapt'
项目 build.gradle
classpath "com.google.dagger:hilt-android-gradle-plugin:2.28-alpha"
2.2 常用的注解
@Inject:可以在类的构造函数中注释,告诉Hilt要创建这个类的实例 @AndroidEntryPoint:可以注释Activity、Fragment、View等,需要注意的就是,在Fragment中注释时,包裹其的Activity容器也需要标注@AndroidEntryPoint
@AndroidEntryPoint
class MathFragment : Fragment() {
private var param1: String? = null
private var param2: String? = null
@AndroidEntryPoint
class NewsActivity : AppCompatActivity() {
private lateinit var mathFragment: MathFragment
@HiltAndroidApp:需要在Application中注释,代表当前应用是一个Hilt项目
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Log.e("TAG","Application onCreate")
DataBaseManager.instance.init(this)
}
}
2.3 @Inject使用方式
class MyViewModel @Inject constructor(private val repository: NewsRepository) : ViewModel() {
fun getUser():MutableLiveData<String>{
return repository.getUser()
}
}
需要注意的就是,@Inject注解属于链式的引用,在当前类中使用Inject注解修饰,那么其形参也需要使用Inject注解修饰构造函数
class NewsRepository @Inject constructor (private val newsDataSource: NewsDataSource) {
fun getUser():MutableLiveData<String>{
return newsDataSource.getUser()
}
}
2.4 @Moudle模块注解使用
但如果参数是接口,没有构造函数,该如何注入依赖
interface INewsDataSource {
fun getUser():MutableLiveData<String>
}
@Module
@InstallIn(ActivityComponent::class)
abstract class NewsDataMoudle{
@Binds
abstract fun NewsDataBinding(
newsDataSource: NewsDataSource
):INewsDataSource
}
解决的方式就是在接口类中创建一个抽象类,向外提供这个接口,其中涉及到的注解有@Module、@InstallIn、@Binds,其中InstallIn中的参数表示向哪些类中注入这个注解,示例中ActivityComponent代表这个接口可以在所有的Activity中使用
@Binds中,需要在参数中配置依赖项,就是当前接口的实现类,告知Hilt要实现哪个类,当前实现类也需要使用@Inject修饰构造函数
|