Android 組件化實戰二: 項目部署

前言

組件化項目的意義主要體現在這幾個方面,首先就是面試的時候,如果簡歷上寫了三五年的工作經歷,但是被問到組件化的相關原理打不上來,確實說不過去。在開發需求層面,即不相互依賴、又可以相互交互、任意組合、高度解耦;在團隊開發效率層面,可以分模塊打包、測試,統一版本管理。

Phone Module和Android Library區別、切換

在這裏插入圖片描述

新建common公共庫、order訂單庫、personal個人信息庫

這裏爲了便於演示,新建Phone Module 的order和Android Library的personal,在組件化部署中如何進行切換

有了上一篇文章的分析,我們知道可以將各個子模塊build.gradle文件中的公共屬性抽取出來到單獨的gradle文件config.gradle文件,在項目根目錄下的build.gradle頭部加入自定義config.gradle,apply from: “config.gradle”,相當於layout佈局中加入include語法

// 添加多個自定義屬性,可以通過ext代碼塊
ext{
    /**
     * 定義一個項目全局變量isRelease,用於動態切換:組件化模式 / 集成化模式
     * false: 組件化模式(子模塊可以獨立運行),
     * true :集成化模式(打包整個項目apk,子模塊不可獨立運行)
     */
    isRelease = false

    // 建立Map存儲,對象名、key都可以自定義,groovy糖果語法,非常靈活

    androidId = [
            compileSdkVersion: 29,
            buildToolsVersion: "29.0.3",
            minSdkVersion    : 21,
            targetSdkVersion : 29,
            versionCode      : 1,
            versionName      : "1.0",
            testInstrumentationRunner: "androidx.test.runner.AndroidJUnitRunner",
            consumerProguardFiles: "consumer-rules.pro"
    ]

    appId = [
            app: "xpf.moudlar.deploy",
            order: "xpf.moudlar.deploy.order",
            personal: "xpf.moudlar.deploy.personal"
    ]

    //生產開發環境URL
    url = [
            "debug_entrance": "https://11.22.33.44/debug",
            "release_entrance": "https://11.22.33.44./release"
    ]

    //依賴相關
    dependencies_impl = [
            appcompat: 'androidx.appcompat:appcompat:1.1.0',
            constraintlayout:'androidx.constraintlayout:constraintlayout:1.1.3',
            junit: 'junit:junit:4.12',
            test: 'androidx.test.ext:junit:1.1.1',
            espresso: 'androidx.test.espresso:espresso-core:3.2.0',
            recyclerView: 'androidx.recyclerview:recyclerview:1.1.0'
    ]

}

在order和personal模塊的build.gradle文件中做如下處理,就可以根據isRelease的值,將order和personal在進行動態切換


if (isRelease) {//集成化環境,正式打包環境
    apply plugin: 'com.android.library'// 配置爲library
} else {// 組件化環境,測試環境,可以單獨運行
    apply plugin: 'com.android.application' // 配置爲phone module
}

android {
    compileSdkVersion androidId.compileSdkVersion
    buildToolsVersion androidId.buildToolsVersion

    defaultConfig {
        if (!isRelease) {// 如果是集成化環境,不能有applicationId
            applicationId appId.personal//組件化模式能獨立運行纔能有applicationId
        }
        minSdkVersion androidId.minSdkVersion
        targetSdkVersion androidId.targetSdkVersion
        versionCode androidId.versionCode
        versionName androidId.versionName
        testInstrumentationRunner androidId.testInstrumentationRunner
        if (isRelease) {
            // 筆者在升級3.6之後,新建android library 發現有有如下屬性
            consumerProguardFiles androidId.consumerProguardFiles
        }

        // 這個方法接收三個非空的參數
        // 第一個參數:確定值的類型
        // 第二個參數:指定key的名字
        // 第三個參數:傳值(必須是String)
        // 爲什麼需要定義這個?因爲在src代碼中有可能需要跨模塊交互,如果是組件化模塊(開發環境)相當於兩個App交互,顯然不行
        // 切記:不能在android節點下,只能在defaultConfig或buildTypes節點下
        // rebuild之後,BuildConfig文件中有boolean isRelease 屬性了,可以通過它判斷環境,進行相關操作
        buildConfigField("boolean", "isRelease", String.valueOf(isRelease))

    }
    buildTypes {
        // 在配置app和librayt切換時,主要前面的部分,通過isRelease進行判斷配置,受篇幅所限,其餘部分省略
        ...
            
    }
}
dependencies {
    ...
}

Gradle搭建組件化項目環境

經過前面的步驟,當isRelease爲false時,各個子模塊均可獨立運行,但是之前創建personal的時候是library,雖然經過配置理論上變成了可獨立運行的app。但是由於沒有AndroidManifest和res目錄下的drawable和layout等資源,運行會報錯。所以還需要將order模塊的AndroidManifest和res目錄下的所以資源拷貝到personal對應目錄,然後更改爲符合personal的條件。

組件化開發規範:

  • order order_前綴(src類和res資源)
  • personal personal_前綴(src類和res資源)
  • app 可不改,讓它默認

此時當isRelease置爲false時,order和personal均可獨立正常運行了,這一部分較爲簡單,代碼就不貼了。

集成化模式開發、組件化模式開發

前面提到過,組件化模式就是isRelease置爲false,各個子模塊可獨立運行,一次打包爲多個apk文件,可以選擇性的進行調試。集成化模式就是isRelease置爲true,各個子模塊不能獨立運行,整個項目打包爲一個apk文件,子模塊此時爲library。

在這裏插入圖片描述

組件化開發的臨時代碼,集成化打包時動態隔離

試想一下,在組件化模式下,需要進行多種業務的調試,可能會創建多個文件,但是在集成化模式下,我們並不希望這些文件打包到apk文件中。此時在order和personal的build.gradle文件中進行如下配置解決這個問題, 這裏只貼出與本問題相關部分的配置

if (isRelease) {
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

android {
    ...
    defaultConfig{
    	...
    }

    buildTypes {
        ...
    }

    // 配置資源路徑,方便測試環境,打包不集成到正式環境
    sourceSets{
        main {
            if (!isRelease) {
            	// 註釋1
                // 如果是組件化模式,需要單獨運行時
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                
                // 註釋2
                // 集成化模式,整個項目打包apk
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    // 註釋3
                    // 集成化時debug目錄下文件不需要合併到工程
                    exclute '**/debug/**'
                }
            }
        }
    }

}

dependencies {
    ...
}

正如註釋處所示,在組件化模式和集成化模式下,指定不同目錄下的AndroidManifest文件,註釋3處,表示集成化模式時,子模塊所有debug目錄下的文件不需要合併到工程,也就不會打包到apk文件中。在需要參照配置創建對應的debug目錄和AndroidManifest文件,在debug目錄下的AndroidManifest中註冊,對應debug目錄下的Personal_DebugMainActivity等文件。當isRelease爲false時,就會顯示Personal_DebugMainActivity對應的內容,但是isRelase爲true時,Personal_DebugMainActivity文件又不會打包到apk文件當中。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章