iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0

Keyword:Koin,Koin Compent
到Day20 使用Koin管理依賴注入顯示在Android上 放在這邊
KMMDay20


我們先在Android使用昨天建立的Koin物件吧.就跟正常的Koin使用流程一樣,需要在Android的App啟動時進行Koin的啟動,因此我們在Android的根目錄建立一個新的物件CafeApplication並且繼承Application,讓Koin可以在這裡啟動,有多第三方庫也會要求使用時必須在Application預先載入.如果有用到其他部分的組件,請務必在Koin之後再開始啟動流程.不然這塊的物件就會超脫Koin的管理,這樣就失去了依賴注入的特性了.

import android.app.Application
import android.content.Context
import com.officeyuli.kmmforit.initKoin
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

class CafeApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        initKoin(
            module {
                single<Context> { this@CafeApplication }
                viewModel { MainViewModel() }
            }
        )
    }
}

在這裡我們呼叫了昨天寫好的一個funcion ,initKoin,回去看initKoin有要求提供一個appModule,這邊就交由各平台實作.那Android這邊有兩個特別的物件建立或提供,第一個就是ApplicationContext,不管是使用DB或是SharedPreferences都需要這個,所以先交給Koin幫我們管理(當然在iOS就沒有需要這個了),在幾天後的DB使用教學就會用到了

另外一個就是ViewModel,在一般的Android App裡面,使用ViewModel的時候需要提供生命週期的宿主,像是某一個Activity或是Fragment,但是我們藉由Koin提供的DSL,可以自動根據ViewModel所在的View層物件,來自動建立對應的ViewModel.是不是很方便呢.

這邊有一點要特別注意,因為viewModel這個Term太多人使用了,在使用Koin的viewModel功能時,要注意不要使用到錯誤的import.所以我今天特別把import加了上去.

接下來要讓Android系統知道啟動的時候要呼叫這個Application,所以修改androidApp內的AndroidManifest.xml.在application的tag內加上指定的Application,也就是剛剛建立的CafeApplication.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.officeyuli.kmmforit.android">

    <application
        android:name=".CafeApplication"//加入這行來指定啟動時使用的預設Application
        android:allowBackup="false"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
         ...
					>
        </activity>
    </application>
</manifest>

然後我們修改MainViewModel,讓其實作KoinComponent這個interface.這是為了讓Koin可以提供,我們不用做特別的動作.

然後根據我們昨天寫的Module,現在Koin知道如何提供DataRepositoy的實體了,那麼我們可以使用by inject()方法,讓Koin來代替我們完成物件的建立.現在MainViewModel不用知道這些物件怎麼建立的了.

class MainViewModel : ViewModel(), KoinComponent {
    private val dataRepository: DataRepository by inject()
    private val cafeList = MutableLiveData<List<CafeResponseItem>>()
    val cafeListLiveData: LiveData<List<CafeResponseItem>> = Transformations.map(cafeList) { it }

    fun fetchCafeData(city: String = "") {
        viewModelScope.launch() {
            val result = async { dataRepository.fetchCafesFromNetwork(city) }
            cafeList.value = result.await()
        }
    }
}

同樣的,Activity內的viewModel宣告,由於Koin已經自動幫我們建立好了ViewModel的建立過程,因此可以由Koin代為效勞.我們把裡面的MainViewModel建立過程替換掉.

import org.koin.androidx.viewmodel.ext.android.viewModel
class MainActivity:AppCompatActivity() {
	...
private val viewModel : MainViewModel by viewModel()
	...
}

同樣要注意viewModel不要用錯了,要import的是koin的.

之前我們的ViewModel是可變數var,而在使用Koin提供後,會要求改變為不可變數val,這樣就不會在使用流程中,再次的重新定義給viewModel變數了.這樣物件的建立與銷毀都由Koin來管理.

執行起來,跟原本的狀態是一樣的,但是MainActivity ,MainViewModel與DataRepository的耦合程度大大的降低了.

今天完成了Android的部分,我們明天會來做iOS的部分


上一篇
Day 19: Let's Koin!Koin 實作依賴注入
下一篇
Day 21: iOS也懂Koin喔?其實是KMM當工具人啦
系列文
挑戰 Kotlin Multiplatform Mobile 跨平台開發,透過共同的Kotlin模組同時打造iOS與Android應用!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言