Kotlin - dagger 2

Dependencies

Project build.gradle
buildscript {
    ext.dagger_version = '2.5'
}
App build.gradle
apply plugin: 'kotlin-kapt'

dependencies {
    implementation "com.google.dagger:dagger:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
}

下面我們直接來看一個範例:
我這邊使用四個Model,分別為Model A B C D
ModelA 裡面包含了 B跟C
ModelC 裡面包含了 D

先看ModelA:
class ModelA @Inject constructor(val context: Context, var modelB: ModelB, var modelC: ModelC){

    var somethingData: String = "modelA haha "

    fun print() {
        Log.d("ModelA", somethingData + modelB.somethingData + modelC.somethingData)
    }
}
傳入的context,實際上沒用到只是純粹練習
 print() 會印出ModelA的data,data會將ABC的data加起來

ModelB:
class ModelB @Inject constructor(){
    var somethingData: String = "modelB haha "
}

ModelC:
class ModelC @Inject constructor(modelD: ModelD){
    var somethingData: String = "modelC haha " + modelD.somethingData
}
ModelC包含ModelD

ModelD:
class ModelD @Inject constructor(){
    var somethingData: String = "modelD haha "
}

AppModule:
@Module
class AppModule @Inject constructor(private val context: Context) {
    
    @Provides
    fun provideModelA(modelB: ModelB, modelC: ModelC): ModelA {
        Log.d("AppModule", "provideModelA")
        return ModelA(this.context, modelB, modelC)
    }

    @Provides
    fun provideModelB() = ModelB()

//    @Provides
//    fun provideModelB(): ModelB {
//        Log.d("ModelB", "provided")
//        return ModelB()
//    }

    @Provides
    fun provideModelC(modelD: ModelD): ModelC {
        return ModelC(modelD)
    }

    @Provides
    fun provideApplicationContext(): Context = context

}

AppComponent
@Component(modules = arrayOf(AppModule::class))
interface AppComponent {

    fun inject(myApplication: MainActivity)
}

實際使用:
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var modelA: ModelA

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        DaggerAppComponent.builder()
            .appModule(AppModule(this))
            .build()
            .inject(this)//必须注入一下

        tv1.setOnClickListener { rx1() }
    }

    private fun rx1() {
        Log.d("DaggerAppComponent", "data" + modelA.print())
    }
}

Inject
在Dagger2中, @Inject 可以用來標記建構子、屬性、以及函式,這裡以標記建構子作為範例。

Module
  1. 生產實例的工廠,每個一個實例都是通過@Provides修飾的方法提供的
  2. 專門解決,不是自己寫的類別無法在其構造函數上加@Inject的情況
  3. 當然自己寫的類別也可以通過@Provides修飾的方法提供,這樣就不會找@Inject的構造函數了
Component
component 是一個橋樑,是一個接口
  1. 一個conponent可以組織多個模塊,一個conponent還可以組織引入其他的組件
  2. 依賴的查找順序為:先找@module,如果找到了就停止,如果找不到就去找@Inject

留言

這個網誌中的熱門文章

Android - 使用 adb 安装apk

Android TextView autosizing 自動調整大小

Kotlin - 實現Android中的Parcelable