考慮Android項目模塊化
已發表: 2019-08-21當一個項目達到一定規模時,在單個模塊中進一步工作就會變得不那麼有效。 然後將其模塊化成為一種有效的解決方案。
模塊化的4大優勢
在決定模塊化之前,最好明確所涉及的內容。 模塊化 android 項目結構的優點包括:
更好的代碼隔離
每個模塊都可以公開其公共 API 接口並隱藏實現細節。 對於單個模塊,您不能完全確定它的實現是否被很好地隱藏(尤其是在 Kotlin 中,其中包可見性修飾符不可用)。
更容易的新技術評估
創建模塊時,您可以在不影響其他模塊的情況下檢查新的架構模式或新庫。
減少項目構建時間
修改一個模塊需要重建該模塊和其他依賴它的模塊。 通過閱讀本文檔了解其工作原理:Android 開發人員。 依賴配置
工作更方便
更容易分析/調試/重構更小的和孤立的代碼片段。 此外,新開發人員的入職速度會更快。
這些好處聽起來足以說服您開始模塊化過程,但是您如何開始呢?
#1:確定您的模塊及其關係
有兩種方法可以識別您的模塊:按功能和按層。
在功能模塊下,您可以了解用戶可用的應用程序的某些區域(例如登錄、儀表板、個人資料等)。 這些區域可以由單個屏幕或涵蓋某些流程的屏幕流組成。 這種類型的模塊不能依賴於相同類型的模塊。
確定特徵後,您肯定需要提取一些甚至所有模塊所需的通用功能。 這些模塊可以負責單獨的架構層(如持久存儲、網絡、導航、UI 組件……)或處理一組功能使用的某些數據的業務邏輯。 這些類型的模塊通常稱為庫。 庫模塊可以構建依賴樹。
除了功能和庫模塊之外,還需要一個模塊來管理其他模塊之間的水平連接(下一點對此進行更多介紹)。 該模塊將包含一個自定義應用程序類和一個依賴注入設置。 沒有其他模塊可以依賴於這個模塊,但是這個模塊依賴於項目中的所有其他模塊。

考慮到上述定義,模塊層次結構可能如下所示:
#2:依賴注入設置
儘管項目模塊之間存在依賴關係,但您還應該設置 dagger 依賴關係。 Dagger 提供了兩種聲明依賴的方式:子組件和組件依賴。
Dagger 子組件依賴要求父組件聲明所有依賴的子組件。 在項目模塊之間,這種關係是行不通的,因為它顛倒了項目模塊依賴的方向。 但它可以在單獨的項目模塊中使用。
Dagger 組件依賴更加靈活,因為子組件可以聲明它依賴於父組件。 這使得在單獨的項目模塊之間使用這種依賴關係成為可能。
在某些時候,您可能會發現一個模塊需要的關於另一個模塊的知識有限。 一個很好的例子是功能模塊之間的導航。 提供這種關係通常稱為水平依賴。 要在單獨的模塊之間創建此通信通道,需要具有接口的附加模塊來描述此通信和將實現綁定到聲明的接口的模塊。
用於管理水平依賴的項目模塊依賴設置如下圖所示:

本文末尾的項目中提供了此類關係的示例代碼。
#3:Gradle 設置
每個項目模塊都有其 gradle.build,除了應用了添加的依賴項和插件外,幾乎相同。 因此,最好將重複配置提取到項目目錄根目錄下的一個 gradle 文件中。 這樣的文件還可以註冊常見的 gradle 任務來執行靜態代碼分析或運行單元測試。

此類常見設置的代碼片段可在此處找到:
afterEvaluate { project -> def isAndroid = project.plugins.hasPlugin('com.android.library') || project.plugins.hasPlugin('com.android.application') setupModule(isAndroid) setupCommonTestDependencies(isAndroid) setupCommonTasks(isAndroid) } def setupModule(isAndroid) { if (isAndroid) { android { compileSdkVersion projectCompileSdk defaultConfig { minSdkVersion projectMinSdk targetSdkVersion projectTargetSdk } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } lintOptions { abortOnError true checkReleaseBuilds false checkAllWarnings true warningsAsErrors true def lintBaseline = file("quality/lint-baseline.xml") if (lintBaseline.exists()) baseline lintBaseline } } } else { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } } def setupCommonTestDependencies(isAndroid) { dependencies { testImplementation "junit:junit:${junitVersion}" testImplementation "org.assertj:assertj-core:${assertJVersion}" testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:${mockitoKotlinVersion}" if (isAndroid) { androidTestImplementation "androidx.test.ext:junit:${axTestJUnitVersion}" androidTestImplementation "androidx.test.espresso:espresso-core:${axEspressoLibVersion}" } } } def setupCommonTasks(isAndroid) { if (isAndroid) { tasks.register("unitTest") { task -> task.dependsOn(testDebugUnitTest) } } else { tasks.register("unitTest") { task -> task.dependsOn(test) } } }
結論
本文並非詳盡無遺,也不是模塊化 Android 項目的完整指南。 但我認為它解決了在開始項目模塊化時應該考慮的方面。
在鏈接中可以找到一段展示水平依賴的代碼。
想要為 Android 構建原生應用程序? 選擇米奇多!