iT邦幫忙

2021 iThome 鐵人賽

DAY 19
0

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)
	...
}

完成後記得同步,就能正式使用了

撰寫Module

我們在使用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,明天我們會來使用它


上一篇
Day 18: To DI ? Or not DI? 依賴注入的存在意義
下一篇
Day 20:讓我來為您服務.由Koin管理的Android App
系列文
挑戰 Kotlin Multiplatform Mobile 跨平台開發,透過共同的Kotlin模組同時打造iOS與Android應用!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言