Android 奇技淫巧:多個 Project 代碼同時引入

背景

從開始學習編程時,老師就告訴我們設計模式、MVC等在編程中非常重要,所以一定要努力學習。在項目設計的時候,爲了更好地解耦,我們往往會將每一個小模塊都設計到了獨立的 module 裏面,但是這樣子雖然做了拆分,卻並不能很好地在各個項目中重用它們。因此筆者做了一個更加嚴格拆分,每一個library都會放在獨立的project中,這樣就可以更好地在不同的項目裏重用library。不僅如此,我們在打開獨立的project時,Android Studio 會運行的更流暢。

每一個library在使用的時候都會被打包成aar,上傳到公司內部的maven服務器,如此進行依賴就可以避免基礎庫遭到亂改。

但是使用這種方式,並不利於源碼的閱讀。因此我們需要將不同的項目引入到同一個工種中進行加載。

引入工程

首先我們來看一下,使用module的時候,是如何引入的,如下:

include ":demo", ":common-android"

現在我們需要把外部工程的 module 也引入進來。要怎麼做呢?

如下:

  1. 使用Android Studio打開作爲主工程的項目

  2. 手動打開主工程項目根目錄下的settings.gradle,添加module的依賴進去

    include ":toolkit"
    
  3. 給引入的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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章