Keyword: Dependency Injection
到Day20 使用Koin管理依賴注入顯示在Android上 放在這邊
KMMDay20
依賴注入(Dependency Injection,簡稱DI),是一種...物件的使用法,主要的目標是降低物件與物件之間的耦合關係.關於相繫確的定義網路上一大堆.
這邊就用我自己的想法介紹吧.
依賴注入,分成了"依賴","注入"兩塊.
所謂的依賴,就是使用到的物件.稱為依賴.像是這樣:
//Kotlin
class People(var air:Air){
val heart:Heart
}
這個例子中,人類沒有心臟(Heart)或是空氣(Air),就無法正常運作.那麼就稱 “人,依賴於心臟及空氣"
這就是依賴關係
既然需要這些重要的部分才能正常運作,那有兩種來源:一種是天生的,另外一個是外來的.
//Kotlin
class People(var air:Air){
val heart:Heart = UnbreakableHeart()
}
像上面這個例子,人類天生就有了一個心臟的實體,所以能正常運作.
那另外一種,由地球媽媽提供空氣:
//Kotlin
class EarthMom(){
val air:Air = FreshAir()
val people:People = People(air)
}
class People(var air:Air){
val heart:Heart
}
有了地球媽媽帶來的空氣,人類也能正常運作了.
而後面這種由外部提供需要的依賴,就稱之為"依賴注入"
其實不難懂對吧?
實際上在使用時,會有一個問題.就是如果某個部分發生了修改,所有依賴到的地方跟著修改,需要修改很多很多地方.
比如說,有一天,人類除了空氣,還需要水.
//Kotlin
class EarthMom(){
val air:Air = FreshAir()
val water:Water = CleanWater()
val people_1:People = People(air,water)
val people_2:People = People(air,water)
...
val people_6Billion:People = People(air,water)
}
class People(var air:Air, var water:Water){
val heart:Heart
}
所以地球媽媽需要去把六十億人都加上water的需求.
但是人類的內容修改,跟地球媽媽有什麼關係呢?
這就是依賴所帶來的耦合,當被依賴的那方改變時,依賴的這方也需要作出調整.
如果有一個全知全能的神,可以提供所需要的任何東西,那麼人類變化就改成直接跟這個人要空氣跟水,不再由地球媽媽提供.那麼地球媽媽與人類的關係就解開了.
透過什麼方法提供呢,就是上面說過的依賴注入.而這個管理一切物件建立與回收的神,我們就稱之為"依賴注入框架"
透過依賴注入框架的幫助,我們解耦了物件之間的依賴關係,所帶來了什麼好處呢?
在Android端,最著名的依賴注入框架,當數Dagger.有名的地方正是超高的學習曲線.有句玩笑話這樣說的“Dagger,從入門到放棄”.由於Dagger是設計給Java使用,而不是給Android專用,因此有非常多需要根據Android的情況而進行的特製.
上面說的,一個依賴注入框架需要管理物件的建立與回收,但是Android的應用端並不能”直接“接觸到Activity或是Fragment的建立與回收.
由於Android App是利用設計模式中的Template模式,僅僅露出了一小部分的開口讓Android工程師發揮,其餘部分則是由系統代為執行,也不讓一般的App有機會修改.例如畫面的測量與描繪,手勢事件的轉換和處理,都是由底層自行處理.這樣的好處就是開發很順暢,不用再去管一些無關緊要的小事,只要告訴系統,在Activity或是Fragment建立的時候順便做什麼事(onCreate/onDestory),或是發生事件時我想做什麼(onTouch/onClick).被系統掌控最明顯的就是,無法掌控App什麼時候被回收,有的時候一退到背景,系統本身就忙著把這個記憶體空間清出來,直接回收了.
也是因為這樣,想要在App端上實作一個依賴注入框架,是十分困難的,隨時要小心系統的背刺.再加上Dagger發生錯誤時通常Log所顯示的並不是真正的問題所在,還會需要為了不同的實作寫許許多的module設定檔,新人只要發生問題往往不知所措.連追蹤都很困難.這也是Dagger勸退很多人的原因之一
我在進行公司專案重構的時候,也曾經考慮到使用Dagger來進行依賴管理,但是考慮到學習成本與帶來的問題,所消耗的時間,最後決定不使用.當然目前也是因為當初的這個決定,依賴上也出現了很多問題,但是如果回到那時候,我仍然會選擇放棄Dagger.這也從側面證明了Dagger到底有多難學和使用.
官方也有注意到這個問題,所以在去年的Jetpack中,加入了Hilt,一個基於Dagger,Android專用的依賴注入框架,Dagger(匕首)加上了Hilt(刀柄),十分輕易好用.如果有新專案,我會推薦Android工程師使用Hilt.
但是這次我們寫的是跨平台KMM,那Hilt這些針對Andriod的優化就無法使用,所以我們這次將使用Kotlin官方推出的另外一套注入框架,針對Kotlin專用的,Koin.