Dagger Hilt,永远滴神

1.简介

大家应该都多多少少了解在Android应用开发中会普遍用到的依赖注入开源库ーDagger2。它能很好帮我们解耦各个模块之间的强关联性,提高项目的健壮性。但是它的羞涩难懂,难用着实吓退了不少人。为了提高易用性,这次谷歌推出了Dagger Hilt。
那么首先我们从Dagger的历史开始讲起吧。
Dagger首先是由Square公司开发。对,Okhttp和Retrofit都是他们家开发的。后来谷歌Fork了这个项目并进行了改进,这就是我们之前一直在用的Dagger2。然后就是这次新推出的Dagger Hilt。

2. 使用方法

2.1 引入库

在模块的build.gradle中加入下列依赖。

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

dependencies {
    implementation 'com.google.dagger:hilt-android:2.28-alpha'
    kapt 'com.google.dagger:hilt-android-compiler:2.28-alpha'
}

然后在项目的build.gralde中加入下面classpath。

buildscript {
    dependencies {
       classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
    }
}

2.2 Application

如果是在Daager2的话,需要Application继承DaggerApplication,并且还需要创建Application的Module,甚是麻烦。 但是这次只要使用@HiltAndroidApp的注解就可以完成对Application的依赖注入。剩下的部分框架会为我们解决。

@HiltAndroidApp
class App : Application() {
}

2.3 Module

Hilt为了方便我们使用提前定义了好多组件的LifeCycle。如下:

  • Application
  • Activity
  • ActivityRetained
  • Fragment
  • Service
  • View
  • ViewWithFragment

以前我们需要自己管理,但是这次只要使用@InstallIn的注解,就可以委托Hilt帮我们管理,可以省去很多麻烦。当然在这里也可以使用@Provide注解。

@Module
@InstallIn(ApplicationComponent::class)
class ApplicationModule {
    @AppHash
    @Provides
    fun provideHash(): String {
        return hashCode().toString()
    }
}

这里的@AppHash是自定义注解,跟Dagger2的用法是一样的。

@Qualifier
@Retention(AnnotationRetention.RUNTIME)

2.4 Activity, Fragment

在Dagger2中,对Activity和Fragment的注入依赖的使用方法异常复杂,让人抓耳挠腮。尤其是新增一个Activity或Fragment时经常忘了添加依赖。 但是在Hilt中为我们简化了这一个过程,只需要@AndroidEntryPoint的注解。相当于之前的@ContributesAndroidInjector。

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    @JvmField
    @ActivityHash
    @Inject
    var hash: String? = null
    private val viewModel by viewModels<MainViewModel>()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        textView.text = hash
        Log.d("MainActivity", viewModel.getRepositoryString())
    }
}

在这里为大家讲几个额外的知识点。

@JvmField

如果要注入的类型包含空,即像上述代码var hash:String? = null时,需要添加@JvmField注解。

@JvmField
    @ActivityHash
    @Inject
    var hash: String? = null

如果只是String类型则不需要。

@ActivityHash
    @Inject
    lateinit var hash: String

生成ViewModel的KTX

如果是正常的生成ViewModel的是方法是使用ViewModelProviders。但是这些代码太过于样板代码,写起来毫无意义。这个时候为了简化这些样板代码就可以使用Activity和Fragment的KTX。

首先把Activity和Fragment的KTX的库引入到项目中。

def activity_version = "1.1.0"
    def fragment_version = "1.2.4"
    implementation "androidx.activity:activity-ktx:$activity_version"
    implementation "androidx.fragment:fragment-ktx:$fragment_version"

还需要设置jvmTarget。

kotlinOptions {
    jvmTarget = "1.8"
}

在Activity中:

// 获取ActivityScope的ViewModel
private val viewModel by viewModels<MainViewModel>()

在Fragment中:

// 获取ActivityScope的ViewModel
private val viewModel: MainViewModel by activityViewModels() 
// 获取FragmentScope的ViewModel
private val viewModel: MainViewModel by viewModels()

2.5 ViewModel

只要使用Hilt的@ViewModelInject的注解,框架不仅为我们解决生成问题,还帮我们解决Lifecycle问题。可算是进一步减少了样板代码的存在。

首先开始之前我们需要添加一下关于ViewModel-lifecycle的库。

dependencies {
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'

    implementation 'androidx.hilt:hilt-common:1.0.0-SNAPSHOT'
    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-SNAPSHOT'
    kapt 'androidx.hilt:hilt-compiler:1.0.0-SNAPSHOT'
}

因为这里我们使用了SNAPSHOT,所以我们还需要添加repository的路径。

allprojects {
    repositories {
        maven {
            url "https://androidx.dev/snapshots/builds/6543454/artifacts/repository/"
        }
    }
}

下面就是关于ViewModel的代码。

class MainViewModel @ViewModelInject constructor(
    private val repository: SampleRepository,
    @Assisted private val savedState: SavedStateHandle
) : ViewModel() {

    fun getRepositoryString(): String = repository.toString()

}

这里的SampleRepository是也是用Hilt生成的,下面会有讲到。 还有@Assisted的注解是为了注入SavedStateHandle。这里就对SavedStateHandle的用途就不叙述了,不懂的小伙伴搜一搜资料了解一下。以后有机会的话会出关于它的教程。

2.6 Singleton

关于Singleton的用法跟Dagger2是完全一样的。怕有人不知道,简单解释一下Singleton就是单例生成,全程持有一个单例,不再额外生成。 关于Singleton的用法参考下面的代码。

@Singleton
class SampleRepository @Inject constructor() {

}

3. 结尾

让我感叹一下,对比之前的Dagger2用法的羞涩难懂,Dagger Hilt真是好用啊。不仅减少了很多样板代码,而且还帮我们管理各个组件的Lifecycle。如果大家有机会一定要尝试尝试!

Github: https://github.com/HyejeanMOON/DaggerHiltDemo

转自:

Dagger Hilt,永远滴神 - 知乎
https://zhuanlan.zhihu.com/p/170470703

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值