以下是我參加 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
參賽總結。