Android 組件化最佳實踐之 AucFrame 統一管理 Gradle

前言

AucFrame 往期文章:php

「AucFrame 之統一管理 Gradle」源碼傳送門java

管理 lib 的 Gradle

首先,咱們再看一遍 AucFrame 的架構圖。android

AucFrameGeneral

咱們從下開始往上搭建,在根目錄建立 lib 文件夾,在項目中新建一個 Android Library 類型的 base module,而後刪除其中的 base.iml,由於不刪除 base.iml 文件的話會影響後續的移動,把 androidTest 以及 test 測試目錄刪了也沒事,而後咱們把 base 文件夾移入到 lib 中,最後咱們修改 setting.gradle 文件中的 ':base':lib:base,最後點擊 Gradle 的同步便可,最終會在 lib 下生成 lib.imlbase 下生成 lib-base.iml 表示成功,結果以下所示:git

lib_base

一樣的方式,咱們建立 :lib:common,接下來配置他們的依賴關係。github

咱們能夠看到 basecommonbuild.gralde 簡直一毛同樣,這樣咱們是否能夠把他們都抽出去呢,答案是確定的。api

咱們在項目根目錄建立 buildLib.gradle 文件,表明全部 lib 類型的模塊均可以使用它,咱們放入公共內容便可,具體以下所示:微信

apply {
    plugin "com.android.library"
    plugin "kotlin-android"
    plugin "kotlin-android-extensions"
}

android {
    compileSdkVersion Config.compileSdkVersion

    defaultConfig {
        minSdkVersion Config.minSdkVersion
        versionCode Config.versionCode
        versionName Config.versionName
    }

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

    lintOptions {
        abortOnError false
    }
}
複製代碼

能夠看到,咱們使用到了 Config.groovy 中的屬性,這樣方便全部 lib 的版本都一致,說到版本一致,那麼咱們還要統一第三方庫的依賴,很簡單,咱們在 Config.groovy 中建立依賴庫的配置,現在它長這樣:架構

class Config {

    static applicationId = 'com.blankj.aucframe'            // TODO: MODIFY
    static appName = 'AucFrame'                             // TODO: MODIFY

    static compileSdkVersion = 27                           // TODO: MODIFY
    static minSdkVersion = 21                               // TODO: MODIFY
    static targetSdkVersion = 27                            // TODO: MODIFY
    static versionCode = 1_000_000                          // TODO: MODIFY
    static versionName = '1.0.0'// E.g. 1.9.72 => 1,009,072 // TODO: MODIFY

    static kotlin_version = '1.3.10'
    static support_version = '27.1.1'
    static leakcanary_version = '1.6.3'

    static depConfig = [
            plugin : [
 gradle: "com.android.tools.build:gradle:3.3.0",
 kotlin: "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version",
            ],
            support : [
 appcompat_v7: "com.android.support:appcompat-v7:$support_version",
                    design : "com.android.support:design:$support_version",
                    multidex : "com.android.support:multidex:1.0.2",
                    constraint : "com.android.support.constraint:constraint-layout:1.1.3",
            ],
            kotlin : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version",
            utilcode : "com.blankj:utilcode:1.25.0",
 free_proguard: "com.blankj:free-proguard:1.0.1",
            swipe_panel : "com.blankj:swipe-panel:1.1",

            leakcanary : [
                    android : "com.squareup.leakcanary:leakcanary-android:$leakcanary_version",
                    android_no_op : "com.squareup.leakcanary:leakcanary-android-no-op:$leakcanary_version",
 support_fragment: "com.squareup.leakcanary:leakcanary-support-fragment:$leakcanary_version",
            ],
    ]
}
複製代碼

接下來就是讓 basecommon 應用它們了,咱們往 basebuild.gradle 寫入以下完整內容:app

apply {
    from "${project.rootDir.path}/buildLib.gradle"
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    api Config.depConfig.utilcode
    api Config.depConfig.free_proguard
    api Config.depConfig.swipe_panel

    api Config.depConfig.support.appcompat_v7
    api Config.depConfig.support.design
    api Config.depConfig.support.multidex
    api Config.depConfig.support.constraint
    api Config.depConfig.kotlin
    compileOnly Config.depConfig.leakcanary.android_no_op.dep
}
複製代碼

因爲咱們 common 模塊是依賴 base 的,因此 common 的配置以下所示:框架

apply {
    from "${project.rootDir.path}/buildLib.gradle"
}

dependencies {
    api project(":lib:base")
}
複製代碼

寫入的內容都比較簡單,我就不一一解釋了,下面咱們來管理 feature。

如今咱們往 base 模塊放兩個基礎類 ———— BaseApplicationBaseActivity,在 common 中放入兩個公共類 ———— CommonApplicationCommonBackActivity 以及一些公共資源,具體請查閱源碼,接下來讓咱們來管理 frature。

管理 feature 的 Gradle

管理 export 的 Gradle

再看一遍架構圖,咱們能夠發現 feature 中每一個 feature 中都存有 app、pkg(、export) 模塊,咱們自底向上來一步步操做,如今咱們在根目錄建立 feature 目錄,在 feature 目錄下建立 feature0 及 feature1 目錄,和建立 base 相似,咱們在 feature0 和 feature1 中建立 export 模塊,注意兩個 feature 中的 export 包名要區分開,我這裏分別是 com.blankj.feature0.exportcom.blankj.feature1.export,創建完以後的 setting.gradle 文件以下所示:

include ':app', ':lib:base', ':lib:common',
        ':feature:feature0:export', ':feature:feature1:export',
複製代碼

因爲 export 是依賴 common 的,因此兩個 exportbuild.gradle 以下所示:

apply {
    from "${project.rootDir.path}/buildLib.gradle"
}

dependencies {
    api project(":lib:common")
}
複製代碼

如今咱們 gradle 同步一下,能夠發現兩個 export 已經被添加進來了。

管理 pkg 的 Gradle

咱們以相同的方式建立兩個 pkg,包名分別是 com.blankj.feature0.pkgcom.blankj.feature1.pkg,創建完後的 setting.gradle 文件以下所示:

include ':app', ':lib:base', ':lib:common',
        ':feature:feature0:export', ':feature:feature1:export',
        ':feature:feature0:pkg', ':feature:feature1:pkg'
複製代碼

pkg 咱們暫時只依賴各自的 export,後面咱們會再改爲全量依賴 export,因此 :feature:feature0:pkgbuild.gradle 以下所示:

apply {
    from "${project.rootDir.path}/buildLib.gradle"
}

dependencies {
    api project(":feature:feature0:export")
}
複製代碼

:feature:feature1:pkgbuild.gradle 同理。

gradle 同步一下,能夠發現兩個 pkg 已經被添加進來了,如今咱們在 :feature:feature0:pkg 中添加一個 Feature0Activity,以及在 :feature:feature1:pkg 中添加一個 Feature1Activity,具體請參看源碼。

管理 app 的 Gradle

pkg 上層就是 mock 層了,由於這層是可選的,咱們暫時先跳過,後面咱們用到的時候再來搞定它,那麼如今就只剩下各個 app 了,首先,咱們利用相似和 buildLib.gradle 類似的方式,在根目錄建立公共的 buildApp.gradle 文件,內容以下所示。

apply {
    plugin "com.android.application"
    plugin "kotlin-android"
    plugin "kotlin-android-extensions"
}

android {
    defaultConfig {
        minSdkVersion Config.minSdkVersion
        versionCode Config.versionCode
        versionName Config.versionName
        applicationId Config.applicationId + suffix
        targetSdkVersion Config.targetSdkVersion
        multiDexEnabled true
        resValue "string", "app_name", Config.appName + suffix
    }

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

    packagingOptions {
        exclude 'META-INF/*'
    }

    dexOptions {
        preDexLibraries true
        javaMaxHeapSize "8g"
        maxProcessCount 8
        dexInProcess = true
    }
}

dependencies {
    // LeakCanary
    debugImplementation Config.depConfig.leakcanary.android
    debugImplementation Config.depConfig.leakcanary.support_fragment
    releaseImplementation Config.depConfig.leakcanary.android_no_op
}

def getSuffix() {
    if (project.path == ":feature:launcher:app") return ""
    return project.path.replace(":", "_").substring(":feature".length(), project.path.length() - ":app".length())
}
複製代碼

這樣咱們在每一個 app 中的 build.gradle 均可以使用這些公共屬性,細心的朋友應該能夠看到我這邊除了 launcher 之外,每一個 applicationId 都是都是帶有 feature 的模塊名後綴的,具體方法就是 getSuffix(),方便咱們在手機上同時裝多個應用。

咱們先刪除根目錄下的 app 目錄,在 feature0 和 feature1 中以相同的方式建立兩個 app,包名分別是 com.blankj.feature0.appcom.blankj.feature1.app,創建完後的 setting.gradle 文件以下所示:

include ':lib:base', ':lib:common',
        ':feature:feature0:export', ':feature:feature1:export',
        ':feature:feature0:pkg', ':feature:feature1:pkg',
        ':feature:feature0:app', ':feature:feature1:app'
複製代碼

app 是隻依賴各自的 pkg,因此 :feature:feature0:appbuild.gradle 以下所示:

apply {
    from "${project.rootDir.path}/buildApp.gradle"
}

dependencies {
    api project(":feature:feature0:pkg")
}
複製代碼

:feature:feature1:appbuild.gradle 同理。

同步一下項目能夠發現兩個 app 也被編譯到了項目中,在可運行 app 列表中已經有了 feature0-appfeature1-app,以下圖所示:

enable_apps

如今咱們在 :feature:feature0:app 中添加一個 Feature0App,以及在 :feature:feature1:app 中添加一個 Feature1App,具體請參看源碼,而後把設置各自的 AndroidManifest.xml,我這裏以 :feature:feature0:app 中的爲例:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.blankj.feature0.app">

    <application android:name="com.blankj.feature0.app.Feature0App" android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme">
        <activity android:name="com.blankj.feature0.pkg.Feature0Activity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
複製代碼

能夠發現,咱們加入了 Feature0Activity 做爲啓動頁,這樣即可快速調試它,同理,:feature:feature1:appAndroidManifest.xml 也是如此,此時咱們即可單獨運行一下它們了,因爲他們的 applicationId 是不一樣的,因此二者能夠同時安裝。

下面,咱們和以前上述同樣的方式來建立最頂層的 :feature:launcher:app 模塊,目前咱們讓它依賴 :feature:feature0:pkg:feature:feature1:pkg 模塊,後續咱們會讓它支持動態化配置,其 build.gradle 以下所示:

apply {
    from "${project.rootDir.path}/buildApp.gradle"
}

dependencies {
    api project(":feature:feature0:pkg")
    api project(":feature:feature1:pkg")
}
複製代碼

把其加入到 setting.gradle 中,同步一下 gradle,會發現可運行 app 中多了個 launcher-app,咱們建立一個 LauncherApp,這裏咱們假設 app 的入口就在 feature0 中,故配置 :feature:launcher:app 中的 AndroidManifest.xml 以下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.blankj.feature0.app">

    <application android:name="com.blankj.feature0.app.Feature0App" android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme">
        <activity android:name="com.blankj.feature0.pkg.Feature0Activity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
複製代碼

咱們把三個應用都裝到手機上,應用名分別爲 AucFrameAucFrame_feature0AucFrame_featrue1,到此,咱們統一管理 Gradle 已結束。

打個小廣告

歡迎加入個人知識星球「基你太美」,我會在星球中分享 AucFrame 框架、大廠面經、AndroidUtilCode 更詳盡的說明...一切我所瞭解的知識,你能夠經過支付進入個人星球「基你太美」進行體驗,加入後優先觀看星球中精華的部分,若是以爲星球的內容對自身沒有收益,你能夠自行申請退款退出星球,也不必加我好友;若是你已肯定要留在個人星球,能夠經過掃描以下二維碼(備註:基你太美+你的星球暱稱)加我我的微信,方便我後續拉你進羣(PS:進得越早價格越便宜)。

個人二維碼
相關文章
相關標籤/搜索