组件化项目部署实例

1、组件化项目的意义

开发需求:不相互依赖、可以相互交互、任意组合、高度解耦
团队效率:分模块打包、测试、统一版本管理>


2、Phone Module和Android Library区别、切换
3、新建common公共库、order订单库、personal个人信息库

模块中有小绿点的是可以单独运行的,模块中有柱状图的是不可以单独运行的。在做组件化模式的时候需要子模块可以独立运行,在做集成化模式的时候需要打包整个项目apk,子模块不可独立运行。

4、gradle搭建组件化项目环境

环境:Android Studio3.4.1+Gradle5.1.1
思考:我们在修改版本号的时候,需要修改各个子模块中的版本号,万一漏了有一个怎么办?这个时候就需要把版本号与引入的第三方库统一管理起来。
\color{red}{在项目的根目录下面新建一个config.gradle文件,用于做版本与引入三方库的统一管理}\

//如果要添加多个自定义的属性,需要在ext代码块中引入
ext {
    // 定义一个项目全局变量isRelease,用于动态切换:组件化模式 / 集成化模式
    // false: 组件化模式(子模块可以独立运行),true :集成化模式(打包整个项目apk,子模块不可独立运行)
    isRelease = false
    // 建立Map存储,对象名、key可以自定义
    androidId = [
            compileSdkVersion: 28,
            buildToolsVersion: "29.0.0",
            minSdkVersion    : 24,
            targetSdkVersion : 28,
            versionCode      : 1,
            versionName      : "1.0"
    ]

    appId = ["app"     : "com.migill.modular",
             "order"   : "com.migill.modular.order",
             "personal": "com.migill.modular.personal"]

    url = [
            "debug"  : "https://11.22.33.44/debug",
            "release": "https://55.66.77.88/release"
    ]
    supportLibrary = "28.0.0"
    dependencies = [
            // ${supportLibrary}表示引用一个变量
            "appcompat"   : "com.android.support:appcompat-v7:${supportLibrary}",
            "recyclerview": "com.android.support:recyclerview-v7:${supportLibrary}",
            "constraint"  : "com.android.support.constraint:constraint-layout:1.1.3",
            "okhttp3"     : "com.squareup.okhttp3:okhttp:3.10.0",
            "retrofit"    : "com.squareup.retrofit2:retrofit:2.5.0",
            "fastjson"    : "com.alibaba:fastjson:1.2.58",
    ]
}

\color{red}{在根目录的build.gradle头部加入自定义gradle}\

apply from: "config.gradle"

\color{red}{修改app模块下的build.gradle文件}\

1、buildConfigField("boolean", "isRelease", String.valueOf(isRelease))这句是什么意思?
是在BuildConfig文件中新增一个isRelease属性。


2、为什么是在isRelease为true的时候引入order和personal 模块?
是因为isRelease为false的时候是组件化模式,order与personal模块都是application模块,application模块是不能引用application模块的。

apply plugin: 'com.android.application'

def rootAndroidId = rootProject.ext.androidId
def appId = rootProject.ext.appId
def support = rootProject.ext.dependencies

android {
    compileSdkVersion rootAndroidId.compileSdkVersion
    buildToolsVersion rootAndroidId.buildToolsVersion
    defaultConfig {
        // app子模块在组件化开发中,默认为application
        applicationId appId.app
        minSdkVersion rootAndroidId.minSdkVersion
        targetSdkVersion rootAndroidId.targetSdkVersion
        versionCode rootAndroidId.versionCode
        versionName rootAndroidId.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        // 切记:不能在android根节点,只能在defaultConfig或buildTypes节点下
        buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    // 循环引入第三方库
    support.each { k, v -> implementation v }
    implementation project(':common') // 公共基础库
    // 如果是集成化模式,做发布版本时。各个模块都不能独立运行了
    if (isRelease) {
        implementation project(':order')
        implementation project(':personal')
    }
}

\color{red}{修改order模块下的build.gradle文件}\

  • isRelease=true:集成化模式(打包整个项目apk,子模块不可独立运行)需要配置成Android Library
  • isRelease=false:组件化模式(子模块可以独立运行)需要配置成Phone Module
if (isRelease) { // 如果是发布版本时,各个模块都不能独立运行
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

def rootAndroidId = rootProject.ext.androidId
def appId = rootProject.ext.appId
def support = rootProject.ext.dependencies

android {
    compileSdkVersion rootAndroidId.compileSdkVersion
    buildToolsVersion rootAndroidId.buildToolsVersion
    defaultConfig {
        if (!isRelease) { // 如果是集成化模式,不能有applicationId
            applicationId appId.order // 组件化模式能独立运行才能有applicationId
        }
        minSdkVersion rootAndroidId.minSdkVersion
        targetSdkVersion rootAndroidId.targetSdkVersion
        versionCode rootAndroidId.versionCode
        versionName rootAndroidId.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    // 循环引入第三方库
    support.each { k, v -> implementation v }
    implementation project(':common') // 公共基础库
}

\color{red}{修改personal模块下的build.gradle文件}\

if (isRelease) { // 如果是发布版本时,各个模块都不能独立运行
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

def rootAndroidId = rootProject.ext.androidId
def appId = rootProject.ext.appId
def support = rootProject.ext.dependencies

android {
    compileSdkVersion rootAndroidId.compileSdkVersion
    buildToolsVersion rootAndroidId.buildToolsVersion
    defaultConfig {
        if (!isRelease) { // 如果是集成化模式,不能有applicationId
            applicationId appId.personal // 组件化模式能独立运行才能有applicationId
        }
        minSdkVersion rootAndroidId.minSdkVersion
        targetSdkVersion rootAndroidId.targetSdkVersion
        versionCode rootAndroidId.versionCode
        versionName rootAndroidId.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        buildConfigField("boolean", "isRelease", String.valueOf(isRelease))
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    // 循环引入第三方库
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    support.each { k, v -> implementation v }
    implementation project(':common') // 公共基础库
}

总结:app、order、personal模块的build.gradle的修改都是围绕如下两点:

  • 第一点,配置成统一管理的版本号等等。
  • 第二点,根据isRelease配置成是组件化模式还是继承化模式
5、集成化模式开发、组件化模式开发
6、组件化开发的临时代码,集成化打包时动态隔离

思考:比如我们在order中创建了A、B、C三个测试类,在集成环境打包的时候,我不希望打包到APK中去,这个怎么办呢?


这个时候就可以用到资源配置,方便测试环境,打包不继承到正式环境

如下图,在main下创建debug目录放AndroidManifest.xml文件,在com.migill.modular.order.debug下放测试的文件

修改isRelease = true,编译正式的APK,可以发现A、B、C、Order_DebugActivity都没有打包到正式环境中。

修改isRelease = false,单独运行order模块。首页就变成了Order_DebugActivity的页面了。

android {
...
    // 配置资源路径,方便测试环境,打包不集成到正式环境
    sourceSets {
        main {
            if (!isRelease) {
                // 如果是组件化模式,需要单独运行时
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                // 集成化模式,整个项目打包apk
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    // release 时 debug 目录下文件不需要合并到主工程
                    exclude '**/debug/**'
                }
            }
        }
    }
...
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353