依賴
項目的gradle
buildscript {
ext.dagger_version = '2.11'
}
module的gradle
//多模塊項目,這個必須在使用到dagger2的所有moudle裏都配置
apply plugin: 'kotlin-kapt'
dependencies {
//dagger2,這個可以寫在BaseMoudle裏
api "com.google.dagger:dagger:$dagger_version"
//多模塊項目,這個必須在使用到dagger2的所有moudle裏都配置
kapt "com.google.dagger:dagger-compiler:$dagger_version"
}
概念
@Inject
- 修飾構造方法
- 修飾變量,在宿主類裏,引入要注入的實例
@Module
生產實例的工廠,每一個實例都是通過@Provides修飾的方法提供的
專門解決,不是自己寫的類無法在其構造函數上加@Inject的情況
當然自己寫的類也可以通過@Provides修飾的方法提供,這樣就不會找@Inject的構造函數了
Component
Component是橋樑紐帶,是一個接口
功能1:組織依賴關係(鏈條)
一個Component可以組織多個Module
一個Component還可以組織引入其他的Component
依賴的查找順序爲:先找@Module,如果找到了就停止,如果找不到就去找@Inject
功能2:爲宿主類提供Inject方法
@Inject+@Component
所有實例類型全部在我掌控之中
最簡單的情況 (不需要Module)
(要注入的實例的類都是自己寫的,不需要Module,自己寫的類自己用@inject修飾構造方法)
構造方法不帶參數
- 注入類的構造方法使用 @Inject
class Apple @Inject constructor(){
var color:String ="red"
}
- 必須有一個FruitComponent接口,提供一個注入方法
注意:參數必須爲要使用對象注入的類
@Component
interface FruitComponent {
fun inject(activity: MainActivity)
}
- 通過inject注入所有對象,@Inject使用注入對象
class MainActivity : AppCompatActivity() {
@Inject
lateinit var apple: Apple//注入實例
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerFruitComponent.builder().build().inject(this)//必須注入一下
tv1.setOnClickListener {
rx1()
}
}
private fun rx1() {
toast(apple.color)
}
}
構造方法帶參數
(但是所帶參數的構造函數,也可以被@Inject修飾,即所帶參數的類型的類也是自己寫的)
class Apple @Inject constructor(val knife: Knife) {
var color: String = "red"
}
class Knife @Inject constructor() {
var name: String = "小刀"
}
@Component
interface FruitComponent {
fun inject(activity: MainActivity)
}
class MainActivity : AppCompatActivity() {
@Inject
lateinit var apple: Apple
@Inject
lateinit var knife: Knife
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerFruitComponent.builder().build().inject(this)
tv1.setOnClickListener {
rx1()
}
}
private fun rx1() {
Log.e("CCC",knife.name)
Log.e("CCC",apple.color)
}
}
@Inject+@Component+@Module(含@Provides)
有些實例類型,我無法掌控
別慌!@Module來幫忙
兩種情況
- 你要注入的實例的類型就不是你自己寫的類,無法使用@inject
- 你要注入的實例的類型就是你自己寫的類,但是帶了一個參數,這個參數類型的類不是你自己寫的,無法使用@inject
情況一
@Module
class SecondModule {
@Provides
fun provideString():String{
return "我是String,你能在我的構造方法上加@inject嗎?是的,你不能!"
}
}
@Component(modules = [SecondModule::class])
interface SecondComponent {
fun inject(activity:MainActivity)
}
class MainActivity : AppCompatActivity() {
@Inject
lateinit var s: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerSecondComponent.builder().build().inject(this)//注入
tv1.setOnClickListener {
rx1()
}
}
private fun rx1() {
Log.e("CCC", s)
}
}
情況二
Person 是我自己寫的類,我可以在它構造方法上面加@inject,但是他有一個參數是String,你要提供Person對象就必須提供Person所需要的所有參數,我們無法在String上加@inject
class Person @Inject constructor(var name: String){
}
@Module
class SecondModule {
@Provides
fun provideString():String{
return "我是爲Person提供name的,但是我是String,你能在我的構造方法上加@inject嗎?是的,你不能!"
}
}
@Component(modules = [SecondModule::class])
interface SecondComponent {
fun inject(activity:MainActivity)
}
class MainActivity : AppCompatActivity() {
@Inject
lateinit var person: Person
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerSecondComponent.builder().build().inject(this)
tv1.setOnClickListener {
rx1()
}
}
private fun rx1() {
Log.e("CCC", person.name)
}
}