以下是我參加 2021 iThome 鐵人賽 所寫的系列文章「寫一個列車抵站時間 Android App」的目錄。原文在 iThome 首次發表,在完賽後轉貼到這裏。
文章示範的 code 可以在 GitHub repo 找到。
- Intro
簡單的開場白,介紹將會提及的內容。 - Architecture
Architecture Components (MVVM)、Modularization 和這次示範 app 所用的 architecture。 - Endpoint
示範 app 會用到的 API endpoint 和 API response 對應的 data class。 - Deserialization
比較 Gson、Moshi、Kotlin Serialization,並為上篇準備的 data class 加上 Kotlin Serialization 的 annotation。 - Dependency injection
為 project 加入 Dagger Hilt。 - HTTP Client
Ktor client 簡介、基本用法及把 Ktor client 加進 Dagger dependency graph。當中提及@Inject
、@InstallIn
、@Singleton
及@BindsOptionalOf
用法。 - Data layer implementation (1)
車站及路綫 enum、domain layer repository interface、實作接駁 API endpoint、Dagger@Binds
用法及 Ktor client 跟 Retrofit 比較。 - Data layer implementation (2)
API response data class 轉換到 domain layer data class 的 mapper。 - Date & time
討論為甚麼要用 Java Time 而不是用 JDK 傳統的Calendar
、Date
的原因、為 project 加入 desugering library 及介紹 Time Zone Database。 - Data layer testing (1)
JUnit 4 test、MockK 及 Strikt 基本用法。 - Data layer testing (2)
用 Strikt 為 object 每個 property 做 assertion。 - Data layer testing (3)
Ktor client 搭配 logback-android 在 unit test 時出現錯誤的解決方法、運用 Ktor mock engine 模擬 server response。 - Data layer testing (4)
運用上篇的 Ktor mock engine 測試觸發 HTTP request 的 code 和經過 Kotlin Serialization deserialize 後的 response object 是否合符預期,另加 Strikt 自定義的 assertion。 - Flipper
安裝 Flipper(只在 debug build type 才安裝)、Dagger Hilt 的@HiltAndroidApp
及@ApplicationContext
用法、Dagger@Qualifier
及@BindsOptionalOf
用法、OkHttp client 加入 interceptor。 - Domain layer implementation
實作 use case。 - Domain layer testing
Use case 的 unit test。 - Navigation (1)
安裝 Navigation component,準備將會用到的Fragment
和 layout XML 檔案、簡單介紹 Dagger Hilt 的@AndroidEntryPoint
及在Fragment
使用 data binding 時要注意的地方。 - Navigation (2)
定義 Navigation graph 並設定轉頁的參數、設定MainActivity
以顯示 navigation graph 的頁面及使用轉頁參數時要注意的地方。 - Station list screen (1)
實作車站列表頁介面,使用了RecyclerView
的ListAdapter
、DiffUtil
、data binding,並示範了 Dagger Hilt 的@ActivityScoped
用法。 - Station list screen (2)
實作車站列表頁的ViewModel
,示範了 Dagger Hilt 的@HiltViewModel
、Kotlin Flow 的Channel
、StateFlow
/MutableStateFlow
、combine
、repeatOnLifecycle
用法和 Navigation component 防止用戶快速連按轉頁按鈕導致 crash 的方法。 - ETA screen (1)
介紹抵站時間頁的流程,實作頁面基本的 layout XML、RecyclerView
、ViewModel
及onBackPressedDispatcher
,另外亦示範了 KotlinSequence
。 - Whistle proxy
安裝 Whistle proxy、Whistle proxy 基本用法、在 Android 裝置安裝根證書、設定 network security configuration 及介紹 Proxy Toggle。 - ETA screen (2)
SavedStateHandle
用法及以 Kotlin Flow 控制各式錯誤介面顯示。 - ETA screen (3)
自動更新班次,介紹 Kotlin Coroutine 的CoroutineScope
、Job
、delay
用法並使用 Java Time 的Clock
取得當前時間。 - ETA screen (4)
顯示錯誤 banner,介紹 Kotlin Coroutine 的scan
(runningFold
) 用法,順帶講解 Kotlin Collection 的fold
和reduce
。 - Station list screen testing
安裝 Robolectric,為引用了 AndroidContext
的 class 寫 unit test;針對 Flipper 在 unit test 時報錯的解決方法;替換Dispatchers.Main
及運用 Turbine 測試 Flow。 - ETA screen testing (1)
示範 JUnit 4 parameterized test;介紹 cold flow (StateFlow
) 跟 hot flow (SharedFlow
) 的分別。 - ETA screen testing (2)
運用 ThreeTen-Extra 提供的MutableClock
及 Kotlin Coroutine 的DelayController
改變時間並測試自動更新班次的邏輯。 - Leftover topics
Two-way data binding、RecyclerView
局部更新、unidirectional data flow、instrumentation test 及 Coroutine dispatcher。 - Wrapping up
參賽總結。