背景
從開始學習編程時,老師就告訴我們設計模式、MVC等在編程中非常重要,所以一定要努力學習。在項目設計的時候,爲了更好地解耦,我們往往會將每一個小模塊都設計到了獨立的 module 裏面,但是這樣子雖然做了拆分,卻並不能很好地在各個項目中重用它們。因此筆者做了一個更加嚴格拆分,每一個library
都會放在獨立的project中,這樣就可以更好地在不同的項目裏重用library
。不僅如此,我們在打開獨立的project時,Android Studio 會運行的更流暢。
每一個library在使用的時候都會被打包成aar,上傳到公司內部的maven
服務器,如此進行依賴就可以避免基礎庫遭到亂改。
但是使用這種方式,並不利於源碼的閱讀。因此我們需要將不同的項目引入到同一個工種中進行加載。
引入工程
首先我們來看一下,使用module的時候,是如何引入的,如下:
include ":demo", ":common-android"
現在我們需要把外部工程的 module 也引入進來。要怎麼做呢?
如下:
使用Android Studio打開作爲主工程的項目
手動打開主工程項目根目錄下的
settings.gradle
,添加module的依賴進去include ":toolkit"
給引入的module指定
projectDir
的路徑(項目文件的真實路徑,建議使用相對路徑)project(":toolkit").projectDir = new File("../toolkit_lib/toolkit")
其中,
../toolkit_lib
爲 toolkit 的項目目錄,這個目錄下是一個完整的AS項目,可以直接打開。
項目依賴處理
按照上面的方式,我們可以在一個項目中查看所有的module的源代碼,但是,在獨立項目中,沒有源代碼,爲解決依賴問題,我們會將每一個module都上傳到maven
服務器,使用路徑地址來進行項目依賴管理。
那麼,問題來了。我們將所有的源代碼都引入到了一個項目中,但是代碼間的跳轉還是使用的maven
中下載下來的代碼庫。
爲了解決這個問題,我們可以定義一個變量來處理,判斷當前module是否是在獨立的項目中,如果是在獨立的項目中,使用maven
庫的依賴,如果是以代碼的形式引入整個項目,則直接使用代碼庫的依賴。
定義變量
在每一個獨立的項目中,在gradle.properties
文件中添加isAlone
屬性,如下:isAlone=true
讀取
isAlone
的值在
build.gradle
文件中,讀取isAlone屬性,如果爲true,依賴maven中的library, 反之依賴project中的。代碼如下:def isAlone = "true" // 默認值爲true // 判斷是否存在isAlone屬性,如果存在,讀取他的值 if (project.hasProperty("isAlone")) { isAlone = project.isAlone } // 如果是獨立項目,使用maven的引用,反之使用project if (isAlone == "true") { project.dependencies.add("compile", "com.knero.test:toolkit:1.0.0@aar") } else { project.dependencies.add("compile", project(':toolkit')) }
在添加依賴的時候,可以使用代碼add的方式,當然也可以直接將不同的dependences放在不同的文件中,然後分情況依賴不同的文件,如下:
if (isAlone == "true") { apply from: 'dependencies_sdk.gradle' } else { apply from: 'dependencies_sdk_proj.gradle' }
不僅是依賴可以通過groovy代碼進行添加,Android的其它屬性也可以添加,Demo如下:
android.sourceSets.main.res.srcDirs = ['res', 'otherRes'] android.sourceSets.main.jniLibs.srcDirs = ['libs', 'otherLibs'] android.sourceSets.main.assets.srcDirs = ['assets', 'otherAssets']
到現在,我們的問題基本解決,但是我追求完美,還一個小瑕疵需要解決。
多項目引入的VCS處理
Android Studio有一個VCS的模塊,他可以快速的在AS中處理git
相關的邏輯。我都會使用他的Modify/New/Rename/Delete/Revert 等功能。但是AS默認只能處理一個項目。所以,導致我們引入的其它Project中的Module不支持git的特點,使用起來非常的不方便。經過一系列的查找,終於找到解決方案。
一個intellij idea項目,在其根目錄下都有一個.idea
的文件夾,這個裏面存儲着整個項目的配置文件,當然也包括git的, 文件名爲vcs.xml
, 默認內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
當然,我們需要更改這個文件,將我們的toolkit_lib文件夾加入到裏面,修改過後如下:
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../toolkit_lib" vcs="Git" />
</component>
</project>
PS: toolkit_lib 和當前引入的項目在同一個文件夾下面,所以使用PROJECT_DIR相對路徑,來指定項目目錄。當然,這個地方的directory, 你也可以使用絕對路徑來指定。
依賴引入的最佳實踐
我們有多個項目需要引入,但是部分項目,沒有修改的需求,並沒有要把項目引入的需求。所以,使用一個變量,來管理所有的項目,使用起來,略顯靈活度不夠。所以,我們將每一個項目按照單獨properties來讀取其狀態,當其中一個項目的dependencies要使用maven,我們只需要將其對應的變量值設置爲true或者刪除掉。讀取屬性的代碼如下:
def isAloneProject = "true"
def propertiesName = "${project.name}Alone"
if (project.hasProperty(propertiesName)) {
isAloneProject = project.property(propertiesName)
}
if (isAloneProject == "true") {
// dependencies maven path.
} else {
// dependencies project path.
}
當作爲module引入的時候,只需要在主Project中的gradle.properties
文件裏面加入對應值。
toolkitAlone=false