Keyword: Koin
到Day20 使用Koin管理依賴注入顯示在Android上 放在這邊
KMMDay20
今天我們就在專案裡面引入Koin進行依賴注入,在目前的這個專案大小剛剛好,不會太簡單導致看不出什麼差別,也不會專案過大導致工作量過多.
首先,照以往一樣,先在buildSrc中加入Koin的引用,來使用這個依賴注入庫
object Versions {
...
val koin = "3.0.0"
...
}
object Deps {
val koinAndroid = "io.insert-koin:koin-android:${Versions.koin}"
val koinCore = "io.insert-koin:koin-core:${Versions.koin}"
val koinTest = "io.insert-koin:koin-test:${Versions.koin}"
}
然後在gradle(android)加入koin的引用
dependencies{
...
implementation(Deps.koinCore)
implementation(Deps.koinAndroid)
...
}
同樣的在gradle(shared)內也有需要用到,也加入.還能順便補上測試版本的引用
sourceSets["commonMain"].dependencies {
...
implementation(Deps.koinCore)
...
}
...
sourceSets["commonTest"].dependencies {
...
implementation(Deps.koinTest)
...
}
完成後記得同步,就能正式使用了
我們在使用Koin的時候,至少需要一個module,這個module將會負責告訴Koin,如何去建立一個物件.當其他程式區塊需要用到這個物件時,Koin就會執行這個區塊來建立一個.所以昨天的例子,如果物件建立的方式改變了,就是改寫module內的建立方法,對於其他使用物件的區塊來說,跟之前沒有任何差別.
當然,我們可以在一個Module內把所有物件的建立方法都放在裡面.但是在一個專案中的物件有成千上萬個,這樣做的話這個Module很容易成長到一個巨大的模樣.不僅使用上不方便,管理上也難以使用.所以我們會建立許多個Module來分門別類管理物件.
我們先來撰寫iOS與Android共用的CafeApi注入吧.這邊是純Kotlin,並且和各平台的實作沒有關係.可以兩邊一起共用,那這個Koin Module 就建立在shared /commonMain底下吧
首先我們在commonMain建立建立一個檔案.就叫做Koin.kt吧
然後加入一個Koin的初始化Function,在App啟動的時候,Koin就必須能夠接手處理物件,才能確保萬無一失.初始化的Function需要在任何動作執行前先被執行過.
fun initKoin(appModule: Module): KoinApplication {
val koinApplication = startKoin {
modules(
appModule//appModule是需要在一開始時帶入的
)
}
val koin = koinApplication.koin //啟動koin
val doOnStartup = koin.get<() -> Unit>() //讓iOS在啟動時呼叫 讓iOS也能追蹤注入框架
doOnStartup.invoke()
val appInfo = koin.get<AppInfo>()//讓雙平台各自實作的資訊 .先暫時不使用
return koinApplication
}
然後我們在下面建立一個Module,來管理資料方面的物件,是最重要的部分就稱為coreModule吧.
private val coreModule = module {
single<CafeApi> {//使用single包覆的物件,在整個專案中會是單例的
CafeApiImpl(//使用CafeApiImpl作為CafeApi的實體
getWith("CafeApiImpl")
)
}
}
internal inline fun <reified T> Scope.getWith(vararg params: Any?): T {
return get(parameters = { parametersOf(*params) })
}
上面的coreModule ,讓Koin了解到,如果將要使用到CafeApi,就使用CafeApiImpl的物件作為注入的物件.並且利用single的scope(這個scope有點類似coroutine的scope,都是限制某件事的生命週期),保證在這個scope中,只會有唯一的CafeApi實體.
這樣做有什麼好處呢?這樣CafeApi就變成了一個所謂的"單一可信訊息源".
在撰寫App時,常常會發生的問題就是:"現在的資料,是不是最新的?會不會在我使用的流程中,這份資料已經修改了?"
由於App的特性,資料變化和使用體驗往往是斷裂的,也就常常發生進到新頁面時需要先確認目前的數據是不是正確的.以避免在切換畫面時,發生數據不一致的情況.例如上一頁還有100筆訊息,結果在切換到下個頁面時變成了200筆訊息.
藉由唯一一個提供資料的訊息源,在不同頁面上由於都是來自同一個源頭,配合觀察者模式,自然就能夠提供一致的體驗.
現在我們建好了Koin 的Module,明天我們會來使用它