Android-架構(gòu)-組件化開發(fā)(一):項(xiàng)目搭建

組件化的優(yōu)點(diǎn)

  • 編譯速度:可以按需測(cè)試單一模塊,因?yàn)槊恳粋€(gè)模塊都可以當(dāng)做一個(gè)application。
  • 超級(jí)解耦:極度的降低了模塊之前的耦合,便于后期維護(hù)。
  • 功能重用:某一塊的功能在另外的組件化項(xiàng)目中使用只需要單獨(dú)依賴這一模塊即可,例如login模塊。
  • 便于團(tuán)隊(duì)開發(fā):適用于大團(tuán)隊(duì)分模塊各自開發(fā),更好地團(tuán)隊(duì)協(xié)作,提升工作效率。

組件化需要注意的點(diǎn)

  • 要注意包名和資源文件名的沖突
  • Gradle中版本號(hào)的統(tǒng)一管理
  • 組件在ApplicationLibrary之間如何做到隨意切換
  • AndroidManifest文件的區(qū)分
  • Library不能在Gradle文件中有applicationId

項(xiàng)目搭建

  1. 項(xiàng)目中新建模塊(membercart

注意:要選擇Application,不要選擇Module

項(xiàng)目結(jié)構(gòu)

各個(gè)模塊都可直接運(yùn)行,因?yàn)槎际?code>Application。

  1. 編寫common.gradle:統(tǒng)一整個(gè)項(xiàng)目各個(gè)模塊的gradle、依賴庫(kù)版本以及配置,放在項(xiàng)目根目錄,與根build.gradle平級(jí)
apply plugin: "com.android.application"
apply plugin: "kotlin-android"

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
}

注意:common.gradle中不要添加applicationId

  1. 各個(gè)模塊apply from: "../common.gradle",刪除通用配置,保留獨(dú)有配置
apply from: "../common.gradle"

android {
    defaultConfig {
        applicationId "com.zt.member"
    }
}

dependencies {
}

注意:applicationId添加到各自模塊中,因?yàn)槊總€(gè)模塊都是唯一的

  1. 使組件在ApplicationLibrary之間隨意切換,其實(shí)就是apply plugin: "com.android.application"還是apply plugin: "com.android.library"
    編寫config.gradle,定義一個(gè)開關(guān)isApplication,也放在跟目錄
ext {
    android = [
            // true:所有組件均為application;false:所有組件均為library
            isApplication: true
    ]
}

切換只需要修改isApplication的值即可。

  1. 在根build.gradle中引用config.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle"
buildscript {
    ...
}

allprojects {
    ...
}
  1. 修改common.gradle
// app模塊一定為application,其他模塊參照配置
if (project.getName() == "app" || rootProject.ext.android.isApplication) {
    apply plugin: "com.android.application"
} else {
    apply plugin: "com.android.library"
}
apply plugin: "kotlin-android"

android {
    ...
}

dependencies {
    ...
}

到此為止,你sync整個(gè)項(xiàng)目,應(yīng)該是可以編過,并且各個(gè)模塊也是可以單獨(dú)編譯成 App 的。
但是,畢竟整個(gè)項(xiàng)目還是一個(gè)完整的 App ,那除了app模塊是Application外,其他模塊應(yīng)該都是Library,那就修改isApplication: false

  1. 修改各個(gè)模塊的gradle文件,因?yàn)槿绻?code>Library的話,是不可以存在applicationId的。
apply from: "../common.gradle"

android {
    defaultConfig {
        if (rootProject.ext.android.isApplication) {
            applicationId "com.zt.member"
        }
    }
}

dependencies {
}

既然是Library,那需要集成到app模塊中

  1. app依賴其他組件,記得也要加上判斷
apply from: "../common.gradle"

android {
    defaultConfig {
        applicationId "com.zt.componentdemo"
    }
}

dependencies {
    // 只有當(dāng)模塊為L(zhǎng)ibrary時(shí),才可以進(jìn)行依賴
    if (!rootProject.ext.android.isApplication) {
        implementation project(path: ":member")
        implementation project(path: ":cart")
    }
}
  1. Androidmanifest文件的區(qū)分,需要使得當(dāng)組件在ApplicationLibrary下加載不同的Androidmanifest.
    在模塊中新建manifest文件夾,路徑:src/main/manifest,復(fù)制一份Androidmanifest.xml到該文件夾,并修改成Library適用的。
    member 模塊

src/main/AndroidManifest.xml

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ComponentDemo">
        <activity android:name=".MemberActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

src/main/manifest/AndroidManifest.xml

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

    <application>
        <activity android:name=".MemberActivity" />
    </application>

</manifest>
  1. 修改common.gradle,添加sourceSets,配置加載不同AndroidManifest文件。
android {
    ...
    sourceSets {
        main {
            // 指定AndroidManifest文件路徑
            if (project.getName() == "app" || rootProject.ext.android.isApplication) {
                manifest.srcFile "src/main/AndroidManifest.xml"
            } else {
                manifest.srcFile "src/main/manifest/AndroidManifest.xml"
            }
        }
    }
}
  1. 如果組件是Application的話,每個(gè)模塊都需要一個(gè)xxxApplication,但是當(dāng)組件變成Library 的話,xxxApplication就不需要了,也不需要打包到最終的app中,那就需要進(jìn)行配置了,思路與AndroidManifest文件類似
    在模塊中新建debug文件夾(名字自?。⑻砑?strong>包名,隨后將臨時(shí)代碼文件添加到該目錄下,如:xxxApplication.java,xxxUtils.java等等
    member 模塊

    并在common.gradle中的sourceSets里添加配置
sourceSets {
    main {
        // 指定AndroidManifest文件路徑
        if (project.getName() == "app" || rootProject.ext.android.isApplication) {
            manifest.srcFile "src/main/AndroidManifest.xml"
            java.srcDirs "src/main/debug"
        } else {
            manifest.srcFile "src/main/manifest/AndroidManifest.xml"
        }
    }
}

注意:請(qǐng)注意debug前面圖標(biāo)的顏色,如果是藍(lán)色(isApplication: true),則表示這里面的java文件會(huì)被編譯進(jìn)app中,如果是灰色(isApplication: false),則表示不會(huì)。

  1. java代碼中區(qū)分模塊類型
    首先現(xiàn)在common.gradle中使用buildConfigField添加參數(shù)
defaultConfig {
    minSdkVersion 21
    targetSdkVersion 30
    versionCode 1
    versionName "1.0.0"
    // 添加參數(shù),便于在java文件中使用 buildConfigField type name value
    buildConfigField "boolean", "isApplication", "$rootProject.ext.android.isApplication"
}

Make Project之后,會(huì)在各個(gè)模塊的BuildConfig文件中生成出該字段,這樣代碼中就可以使用了。

BuildConfig 路徑

  1. 最后,可以再建立個(gè)common模塊,這里新建選擇Library即可
    common 模塊

別忘了在common.gradle中添加依賴

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation "androidx.core:core-ktx:1.3.2"
    implementation "androidx.appcompat:appcompat:1.2.0"
    implementation "com.google.android.material:material:1.2.1"
    implementation "androidx.constraintlayout:constraintlayout:2.0.2"

    implementation project (path: ":common")
}

整個(gè)項(xiàng)目已搭建完成,組件化開發(fā)中還有最重要的兩個(gè)點(diǎn),路由和通信,會(huì)在后面兩篇文章中進(jìn)行分享。

github地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容