本篇文章將介紹如下內(nèi)容
相關(guān)代碼在這里DaggerDemo
-
Dagger2 兩種基本使用方式
- 通過(guò)@Inject注解
- 通過(guò)@Module注解
@Provides注解方法參數(shù)(遞歸注入)
Dagger2眾所周知是一個(gè)依賴注入庫(kù)篓叶,簡(jiǎn)單粗暴的說(shuō)法就是幫助完成一個(gè)類初始化/實(shí)例化捂掰。
Dagger2 配置
- 需要在Module中build.gradle
apply plugin: 'kotlin-kapt'
- 再引入dagger庫(kù)和注解處理器
implementation 'com.google.dagger:dagger:2.16'
kapt 'com.google.dagger:dagger-compiler:2.16'
Dagger2 兩種基本使用方式
通過(guò)@Inject注解
- 因?yàn)槟阋跏蓟粋€(gè)對(duì)象毛好,肯定一個(gè)構(gòu)造方法靠柑,所以在構(gòu)造方法加一個(gè)@inject
class Person @Inject constructor() {
var name = ""
fun test(context:Context){
Toast.makeText(context,"名字:$name",Toast.LENGTH_SHORT).show()
}
}
- 然后通過(guò)一個(gè)@Component來(lái)將這個(gè)對(duì)象跟你注入的地方聯(lián)系起來(lái)(Component類還有另外一種定義方法,會(huì)在下篇文章說(shuō)明)
@Component
interface MainComponent {
fun inject(activity: MainActivity)
}
-
點(diǎn)擊一個(gè)綠色的錘子草慧,會(huì)自動(dòng)生成一個(gè)DaggerMainComponent文件(如下圖)蹬碧,然后你在想要的地方通過(guò)這個(gè)文件完成注入
class MainActivity : AppCompatActivity() {
@Inject
lateinit var person: Person
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerMainComponent.builder().build().inject(this)
person.name = "測(cè)試"
btn_inject.setOnClickListener{
person.test(this)
}
}
}
這種情況適用于你知道構(gòu)造方法或者你可以為構(gòu)造方法增加@Inject注解色鸳。但是如果是第三方的類或者是接口就需要下面這種方式
通過(guò)@Module注解
- 創(chuàng)建一個(gè)接口和它的實(shí)現(xiàn)類()
接口類
interface IJob {
fun work(context: Context)
}
實(shí)現(xiàn)接口類
class Programmer : IJob {
override fun work(context: Context) {
Toast.makeText(context, "敲代碼", Toast.LENGTH_SHORT).show()
}
}
- @Module這個(gè)注解類來(lái)給Dagger提供之后需要注入的初始化方法(由@Provides標(biāo)識(shí))
@Module
class MainModule {
/**
* 初始化接口
*/
@Provides
fun provideIJob():IJob{
return Programmer()
}
/**
* 初始化第三方
*/
@Provides
fun provideGson():Gson{
return Gson()
}
}
- 在@Component注解中與@Module注解的類聯(lián)系起來(lái),賦值給modules的是一個(gè)class的數(shù)組(從 Kotlin 1.2 開始, 注解中的數(shù)組類型參數(shù), 可以通過(guò)新的字面值語(yǔ)法來(lái)指定, 而不必使用 arrayOf 函數(shù))
@Component(modules = [(MainModule::class)])
interface MainComponent {
fun inject(activity: MainActivity)
}
- 在Activity中识脆,方式二適用于需要對(duì)@Module注解類做一些相關(guān)操作
class MainActivity : AppCompatActivity() {
@Inject
lateinit var job:IJob
@Inject
lateinit var gson:Gson
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//方式一
DaggerMainComponent.builder().build().inject(this)
//方式二
DaggerMainComponent.builder().mainModule(MainModule()).build().inject(this)
btn_module.setOnClickListener{
job.work(this)
val json = gson.toJson(person)
Log.d("==",json)
}
}
}
@Provides注解方法參數(shù)(遞歸注入)
比如我們更改Programmer的構(gòu)造方法為多參
class Programmer(val content:String) : IJob {
override fun work(context: Context) {
Toast.makeText(context, "工作內(nèi)容:$content", Toast.LENGTH_SHORT).show()
}
}
把之前@Provides注解的方法改為
@Provides
fun provideIJob(content:String):IJob{
return Programmer(content)
}
編譯之后就會(huì)發(fā)現(xiàn)報(bào)錯(cuò)
錯(cuò)誤: [Dagger/MissingBinding] java.lang.String cannot be provided without an @Inject constructor or an @Provides-annotated method.
這句話意思String類沒(méi)有提供@Inject注解的構(gòu)造方法或者@Provides注解的方法设联。
也就是說(shuō)如果發(fā)現(xiàn)@Provides注解的方法有參數(shù),便會(huì)遞歸尋找這個(gè)參數(shù)的類的@Inject注解的構(gòu)造方法或者@Provides注解的方法灼捂。
如果要改為正確應(yīng)該這樣子离例,增加返回String的方法
@Provides
fun provideContent():String{
return "敲代碼"
}
最后一點(diǎn),如果一個(gè)類同時(shí)使用了@Provides和@Inject悉稠,@Provides優(yōu)先級(jí)是高于@Inject