
Now in Android 模塊化學習之旅app/feature/core三層 Gradle 模塊劃分實戰解析【免費下載鏈接】nowinandroidA fully functional Android app built entirely with Kotlin and Jetpack Compose項目地址: https://gitcode.com/GitHub_Trending/no/nowinandroid本文以 Now in AndroidNiA官方倉庫的 ModularizationLearningJourney.md 為主線系統講解該應用如何將功能拆分為app、featureapi/impl 雙子模塊與core三類 Gradle 模塊并結合settings.gradle.kts、TopicNavKey等源碼證據幫助讀者掌握模塊依賴規則、導航解耦方式與依賴圖維護流程可直接遷移到自己的多模塊 Android 項目中實踐。學習路徑概覽為什么 NiA 要這樣拆分模塊模塊化Modularization是把大型應用拆分為多個獨立、可復用模塊的工程實踐。Now in Android 是一個完全基于 Kotlin 與 Jetpack Compose 構建的完整功能型示例應用其倉庫中每個模塊的 README 都附帶一張模塊依賴圖例如:app模塊依賴圖可以用來快速理解整個項目的結構。有關模塊化的完整官方理論可參考 Android 官方模塊化指南。本文檔的核心價值在于它不止給出了 NiA 的模塊清單更明確了三類模塊各自的邊界、它們之間的依賴規則誰可以依賴誰、誰絕不能依賴誰以及這些規則在真實源碼中的落地形態。下面的 Mermaid 圖概括了 NiA 中app、feature、core三類模塊的典型關系完整圖例參見 docs/ModularizationLearningJourney.md 中的模塊類型圖圖中圖例約定如下app通過虛線implementation依賴引用各個feature模塊android-library類型的core模塊通過實線api依賴向jvm-library模塊暴露 API。Top tip在模塊化規劃階段先畫出一張模塊圖來可視化各模塊之間的依賴關系是非常有效的規劃手段——本倉庫用 Mermaid 以代碼形式維護這張圖天然適合評審與自動化校驗。NiA 的三類模塊及其職責邊界Now in Android 將全部模塊劃分為三類每一類都有明確的職責與依賴約束完整模塊清單見 settings.gradle.kts 中的include聲明。app模塊一切代碼的組裝者app模塊包含應用級與腳手架類負責把其余代碼庫綁在一起典型實現包括MainActivityapp/src/main/.../MainActivity.kt應用入口 ActivityNiaAppNiaApp.kt根 Compose 組合承載主題、漸變背景、離線 Snackbar 與頂部應用欄應用級導航通過NiaNavHost與TopLevelDestination組織頁面跳轉。在NiaApp.kt中可以看到app模塊如何指揮各 feature 模塊它通過entryProvider同時注冊了forYouEntry、bookmarksEntry、interestsEntry、topicEntry、searchEntry五個入口并通過 TopLevelNavItem.kt 中的TOP_LEVEL_NAV_ITEMS映射ForYouNavKey、BookmarksNavKey、InterestsNavKey到對應的圖標與標題資源——這些 NavKey 全部來自各 feature 的api模塊app 只負責把它們組合進導航體系這正是應用級腳手架的體現。app模塊依賴所有feature模塊以及必需的core模塊。從 app/README.md 的完整依賴圖可以看到:app以implementation方式指向:feature:*:api、:feature:*:impl、:sync:work以及:core:analytics、:core:common、:core:data、:core:designsystem等還與:benchmarksBaseline Profile 測試 APK存在雙向虛線關聯。feature模塊單點職責 api/impl 雙子模塊feature 模塊處理應用中單一職責的功能。例如ForYou功能負責 ForYou 屏幕的全部內容與 UI 狀態包括首次運行的引導流程。NiA 中 feature 模塊本身不是獨立的 Gradle 模塊而是被拆成兩個子模塊api—— 只包含導航鍵navigation keysimpl—— 包含其余所有內容UI 組件、ViewModel 等。這種拆分帶來兩個關鍵能力跨功能導航解耦功能 A 可以通過目標功能 B 的api模塊中的導航鍵跳轉到功能 B而不需要了解 B 的任何內部實現。復用與隔離api/impl子模塊可以被任何應用使用包括測試或帶 flavor 的應用。一個類如果只被某一個 feature 用到就留在該 feature 內如果被多個功能共享則應下沉到合適的core模塊。feature 模塊的依賴鐵律api模塊不得依賴其他 feature 的api或impl模塊impl模塊只能依賴其他 feature 的api模塊不得依賴其他 feature 的impl兩個子模塊都只能依賴它們確實需要的core模塊。這條規則在源碼中可以得到直接驗證。以 feature/topic/impl/build.gradle.kts 為例feature:topic:impl的依賴只有projects.core.data、projects.feature.topic.api以及測試相關的core:testing完全沒有觸碰其他 feature 的impl。core模塊跨模塊共享的公共庫core模塊是包含輔助代碼與特定依賴的公共庫供應用內其他模塊共享。它們可以依賴其他 core 模塊但絕不能依賴 feature 模塊或 app 模塊。NiA 的 core 層非常豐富從 settings.gradle.kts 可以看到至少包括analytics、common、data、data-test、database、datastore、datastore-proto、datastore-test、designsystem、domain、model、navigation、network、notifications、screenshot-testing、testing、ui。注意其中common、model、datastore-proto是純 JVM 庫jvm-library在依賴圖中以紫色標記可以顯著提升單元測試速度與構建緩存命中率。雜項模塊除上述三類外NiA 還有一批特殊模塊sync含sync:work與sync:sync-test負責后臺同步、benchmarksMacrobenchmark 基準測試、ui-test-hilt-manifest、lint以及app-nia-catalog—— 一個專門用于快速展示設計系統的目錄應用可在 IDE 中通過app-nia-catalog運行配置查看 design system。模塊示例對照表從文檔到源碼逐一對號入座原文檔用一張對照表說明每個模塊的職責與關鍵類以下結合倉庫源碼逐一印證模塊職責關鍵類與實例app將應用正常運轉所需的一切綁定在一起包括 UI 腳手架與導航NiaApp、MainActivity通過NiaNavHost、NiaAppState、TopLevelDestination當前倉庫中對應 TopLevelNavItem.kt 與 NiaAppState.kt實現應用級導航feature:*:api提供其他 feature 可用的導航鍵與導航函數TopicNavKey見下節源碼分析feature:*:impl特定功能或用戶旅程的完整實現通常包含 UI 組件與 ViewModel并從其他模塊讀取數據feature:topic:impl的TopicScreen、TopicViewModelTopicScreen.kt、TopicViewModel.ktfeature:foryou:impl展示用戶新聞流與首次運行引導core:data從多個數據源獲取應用數據供不同 feature 共享TopicsRepositoryTopicsRepository.kt等倉庫接口其默認實現為OfflineFirstTopicsRepositorycore:designsystem設計系統核心 UI 組件多為定制化的 Material 3 組件、應用主題與圖標可通過app-nia-catalog運行配置預覽NiaIcons、NiaButton、NiaThemecore:ui供 feature 模塊使用的復合 UI 組件與資源如新聞流。與designsystem不同它依賴數據層因為要渲染NewsResource等模型NewsFeed、NewsResourceCardExpandedcore:common模塊間共享的通用類NiaDispatchers、Resultcore:network發起網絡請求并處理來自遠程數據源的響應RetrofitNiaNetworkApicore:testing測試依賴、測試倉庫與工具類NiaTestRunner、TestDispatcherRulecore:datastore使用 DataStore 存儲持久化數據NiaPreferences、UserPreferencesSerializercore:database使用 Room 的本地數據庫存儲NiaDatabase、DatabaseMigrations、各Dao類數據庫 schema 版本見 core/database/schemas/.../NiaDatabasecore:model全應用共享的模型類TopicTopic.kt、Episode、NewsResource一個值得注意的細節core:ui依賴數據層如NewsResource模型而core:designsystem不依賴這說明 NiA 刻意把純展示組件與綁定了業務模型的復合組件分成兩個 core 模塊從而讓設計系統保持最大程度的可復用性。跨模塊導航的解耦范式TopicNavKey實例剖析文檔以:topic:api與:interests:impl的交互作為 feature 間導航的標準范式。真實的 TopicNavKey.kt 實現如下Serializable data class TopicNavKey(val id: String) : NavKey fun Navigator.navigateToTopic( topicId: String, ) { navigate(TopicNavKey(topicId)) }可以看到TopicNavKey是一個Serializable的 data class實現androidx.navigation3.runtime.NavKey攜帶目標話題的id作為導航參數navigateToTopic是Navigator的擴展函數內部直接navigate(TopicNavKey(topicId))。這個范式下:interests:impl只需依賴:topic:api即可在用戶點擊某個 topic 時調用navigateToTopic(topicId)從InterestsScreen跳到TopicScreen。Navigator與導航狀態的定義在 core/navigation并有對應的 NavigatorTest.kt 單元測試驗證導航邏輯。整個鏈路驗證了文檔的結論feature 間通過 api 模塊暴露的導航鍵通信實現徹底解耦這正是 api/impl 拆分最重要的工程收益。依賴圖的維護README 圖、Build.yaml 與graphUpdate任務每個模塊的README.md都包含一張模塊圖例如:app模塊依賴圖。這些圖不是手工維護的靜態圖片而是與代碼同步的 Mermaid 文本塊。當模塊依賴發生變化時圖會由 Build.yaml 工作流自動更新。具體機制見該工作流第 81 行與第 93 行./gradlew graphUpdate工作流中運行./gradlew graphUpdate重新生成各模塊 README 中的依賴圖若圖與當前依賴不一致例如開發者改了依賴但沒更新圖第 93 行會輸出錯誤提示Check Graphs failed, please update graphs with: ./gradlew graphUpdate并使 CI 失敗強制開發者提交同步的圖。開發者也可以在本地手動運行graphUpdate任務刷新所有 README 圖。這一做法把架構圖漂移問題變成了 CI 可檢查項值得在大型多模塊項目中借鑒。模塊化程度的權衡過度模塊化 vs 面向未來擴展NiA 的模塊化方案是結合項目路線圖、規劃中的工作與新特性反復推敲后確定的。其核心目標是在過度模塊化一個小型應用與用這個機會展示適合更大代碼庫、更接近生產環境真實應用的模塊化模式之間找到平衡。原文檔docs/ModularizationLearningJourney.md給出的關鍵建議值得強調模塊化沒有唯一正確答案應用大小、代碼庫現狀與團隊偏好不同方案必然不同。很少有哪一種方式適合所有場景。規劃先行動手前先明確目標、要解決的問題、未來工作與潛在障礙是定義最合適結構的關鍵步驟。可以組織一次頭腦風暴把模塊與依賴畫成圖來可視化規劃。按需調節粒度granularity粒度指代碼庫由多少模塊組成。數據層規模小的時候放在單一模塊完全沒問題一旦倉庫與數據源數量增長就值得考慮拆分為獨立模塊。保持演進心態NiA 的方案并非一成不變的結構未來仍可能演進它只是一個最適合本項目的通用指導方針開發者可以在其上繼續修改、擴展。例如通過提高代碼庫粒度來進一步拆分。這也與倉庫中core模塊的豐富分層相互印證NiA 把數據、數據庫、網絡、DataStore、設計系統、UI、領域層等都拆成了獨立 core 模塊正是按需擴展粒度的具體示范。小結把 NiA 的模塊化經驗移植到自己的項目回顧全文Now in Android 的模塊化方案可以提煉為四條可直接落地的經驗三層職責劃分app負責組裝與腳手架feature負責單點業務功能core負責跨模塊共享的基礎能力三者依賴方向嚴格單向feature → coreapp → 一切。api/impl 雙子模塊feature 對外只暴露導航鍵用Serializable的NavKeyNavigator擴展函數實現無實現依賴的跨功能跳轉可測試、可復用、可替換。依賴規則顯式化api不依賴其他 featureimpl只依賴其他 feature 的apicore 不依賴 feature/app——這些約束在build.gradle.kts中可審計、可強制。架構圖自動化用 Mermaid 在 README 中維護模塊圖通過./gradlew graphUpdate與 Build.yaml 工作流保證圖與代碼一致。最后請記住這不是唯一正確的方案而是 NiA 團隊在社區反饋與項目實際約束下給出的一個高質量參照系。閱讀源碼時可以從 settings.gradle.kts 的模塊清單出發對照 app/README.md 的完整依賴圖再逐個深入各 feature 與 core 模塊的源碼與測試構建起對多模塊 Android 應用架構的完整認知。【免費下載鏈接】nowinandroidA fully functional Android app built entirely with Kotlin and Jetpack Compose項目地址: https://gitcode.com/GitHub_Trending/no/nowinandroid創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考