資料已經讀進來,那麼接下來要 Follow MVVM 的架構和資料溝通方法
接下來教學主體都會圍繞著這張圖
當資料的來源有多個時,使用 Repository Pattern
來處理算是滿常見的操作,透過 Repository
層接收多個來源的資料,然後開放特定的接口釋出資料,當外部物件操作資料時只能透過這些接口來存取,例如上面那張圖的資料來源就有兩個
那麼 ViewModel 需要操作資料就必須透過 Repository 的接口
那該要怎麼開始呢?
依照我目前的經驗是只要和異步工作有關的,那應該都會在 Repostirory 層處理,因為不論是從 DB 或是 Server 取資料,都是需要花時間去等待資料回來的,因此在這樣的前提下我們可以開始撰寫 Retrofit
的 Repository
那首先先來處理 PirateList
的部份,那根據昨天和前天完成的 Code ,今天就是要把他們搬到 Repository
層,然後在把異步的部份處理的更完善
PirateListRepository.kt
在 data/repository
中建立 PirateListRepositroy.kt
的檔案
PirateService
前天在 MainActivity 有簡單的驗證 Retrofit
是可行的,那時是先實作 PirateService
,因此這邊的概念也是一樣,要先把 PirateService
實作起來,因此在 Class 中先加入下面的 Code
private val pirateService: PirateService =
NetworkManager.provideRetrofit(NetworkManager.provideOkHttpClient()).create(PirateService::class.java)
Suspend Function
非同步取得資料Kotlin 本身有支援協程( Coroutine ),那我們可以在函式前面加上 Suspend
裝飾詞,告訴 Compiler 這個函式是允許函式被暫停( Suspended ),並在之後再回復( Resumed )執行,那會有這樣的作法就是不希望一個 Job 鎖住太久的 CPU 資源,適當的釋放資源讓其他 Job 也有機會被同時完成,更詳細的介紹會在下面補上
因此這邊就要先創建一個 suspend fun
並取名為 fetchPirateList
,其中可以注意到
fetchPirateList
帶了兩個 function 當作參數,目的是要做 Callback
flow
,flow
是 kotlinx-coroutines 支援的異步方法,很多人會拿他和 RxJava
做比較,因為他們要處理的問題是相同的Dispatchers.IO
,告訴 flow
裏面的工作需要跑在 worker thread 上,通常會用來執行比較耗時的 Jobsuspend fun fetchPirateList(
onSuccess: () -> Unit,
onError: (String) -> Unit
) = flow {
val response = pirateService.fetchPirateList()
response.suspendOnSuccess {
if (data != null) {
val pirates: List<Pirate> = data?.results ?: listOf()
emit(pirates)
onSuccess()
}
}.onError {
onError(message())
}.onException {
onError(message())
}
}.flowOn(Dispatchers.IO)
因此完整看起來會是這樣
那上面沒有提到的是 Flow Library 需要加到 dependencies
才能使用
dependencies {
...
// kotlinx.coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
...
}
PirateDetailRepository.kt
那同樣的作法我們可套用到 fetchPirateInfo
中
那這邊可以注意到一件事,是我採用了 safe cast
和 Elvis Operator
做 data
與 PirateInfo
之間的轉型,這樣可以確保不會有 null
的發生,頂多建出一個 id = 0
的 PirateInfo
物件
今天介紹了 Repository
大概會處理哪些東西,以及大致上架構會長怎樣,那目前應該只需要這兩個 Repository
,如果之後還需要其他 Repository
會在另外建立
今天寫完也讓我找到明天要介紹的題目就是 Coroutine
,這也是我近期一直鬼打牆的部份,剛好可以透過這的整理看能不能突破以前自己一直沒搞清處的部份