Android Clean Architecture 架構指南
隨著 App 規模變大,如果把所有程式碼都寫在 Activity 或 Composable 中,很快就會變成一團難以維護的義大利麵 (Spaghetti Code)。
Google 官方推薦的現代 Android 架構 (Guide to App Architecture) 基於 Clean Architecture 與 MVVM (Model-View-ViewModel) 模式,將應用程式分為三層。
UI 層 (Presentation Layer)
這一層負責顯示資料與處理使用者互動。
- Views / Composables:負責渲染畫面。
- ViewModel:負責持有 UI 狀態 (UI State) 並處理業務邏輯。它不應該持有任何 Android Framework 的引用 (如 Context),以利於單元測試。
資料流向:
- ViewModel 暴露
StateFlow給 UI 觀察。 - UI 觸發 Event 呼叫 ViewModel 的函式。
Domain 層 (可選)
這一層封裝了複雜的業務邏輯。它由 Use Cases (Interactors) 組成。
例如:GetFormattedDateUseCase, CalculateTotalCartPriceUseCase。
- 它不依賴 UI 層。
- 它不依賴 Android Framework。
- 它只依賴 Data 層。
這層是純粹的 Kotlin/Java 程式碼,最容易測試。對於簡單的專案,這層可以省略,邏輯直接寫在 ViewModel。
Data 層
這一層負責提供資料。它隱藏了資料來源的細節 (是來自網路、資料庫、還是快取?)。
- Repository:對外暴露資料介面。它是 Single Source of Truth。它負責協調不同的 Data Source。
- Data Source:實際存取資料的物件。
RemoteDataSource(Retrofit, API)LocalDataSource(Room, DataStore)
架構範例
假設我們要開發一個「顯示新聞列表」的功能:
- NewsScreen (UI):監聽
NewsViewModel.uiState,顯示列表。點擊新聞時呼叫viewModel.openNews(id)。 - NewsViewModel (Presentation):呼叫 Repository 取得新聞,將結果轉換為
UiState.Success(newsList)。 - NewsRepository (Data):檢查有沒有快取?
- 有:從
NewsDao(Room) 讀取。 - 無:從
NewsApiService(Retrofit) 下載,存入 Room,再回傳。
- 有:從
為什麼要這樣設計?
- 關注點分離 (Separation of Concerns):UI 只管顯示,Data 只管資料,各司其職。
- 可測試性:每一層都可以獨立進行單元測試 (Unit Test)。
- 可維護性:更換資料來源(例如從 SQLite 換成 Realm)只需要修改 Data 層,UI 層完全不需要動。