再聊组件化+gradle简单语法

组件化的目的

单工程项目缺陷

  • 1.各种业务代码在一个模块里,定位问题需要在多个业务混合的模块中找
  • 2.每个开发都要了解各个模块的业务,不然小的改动可能影响到其他业务
  • 3.编译代码的时间随着工程变大而变长
  • 4.多人协作开发,开发风格不一,业务又无法分割,互相影响,效率低下
  • 5.代码复用性差,写过的代码很难复用

组件化的好处

组件化基于可重用的目的,拆分为独立组件,减少耦合

  • 1.分为多个模块,每个模块一个组件,业务分离
  • 2.组件可以单独运行,解决编译耗时问题
  • 3.多人开发,每个人负责自己的模块,降低开发人员沟通成本,减少因为代码风格不一而产生的影响
  • 4.哪个组件坏了系统仍可继续运行,低耦合高内聚

模块化与组件化的区别?
模块化就是将功能拆分为独立的模块,比如登录模块,消息模块
组件化比模块化粒度更小,一个模块包含一个或者多个组件

插件化与组件化的区别?
插件化也是将功能拆分为独立的模块,区别是插件化的模块都是一个个APK,打包时将宿主APK和插件APK分开打包,程序运行时,宿主APK可以动态的选择加载插件APK

  • 组件化在调试的时候可以切换为application,打包的时候确还是library,应用只有一个apk
  • 插件化是拆分出多个apk,运行的时候通过动态加载来加载这些apk

组件化要考虑的问题?
组件分层 ,组件单独运行和调试,组件之间通信,组件生命周期
可参考如下组件分层
在这里插入图片描述

下面通过代码快速简单搭建一个

先看一下结构分层:settings.gradle

app:主工程
bss:业务组件层
func:功能组件层
base:基础组件

rootProject.name = "zkt"
include ':app'
include ':bss:trade'
include ':bss:zkp'
include ':func:pay'
include ':func:share'
include ':base:libBase'
include ':base:libRouter'

接下来看看各个build.gradle配置

最外层project下的build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = "1.3.72"
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url "https://jitpack.io" }
        maven { url 'https://repo1.maven.org/maven2/' }

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.4'
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url "https://jitpack.io" }
        maven { url 'https://repo1.maven.org/maven2/' }

        flatDir {
            dirs 'libs'
            dirs project(':base:libBase').file('libs')
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

//-----------------------------------------自定义配置---------------------------------------------
ext {
    app = "${rootDir}/app.gradle"
    lib = "${rootDir}/lib.gradle"
    bss = "${rootDir}/bss.gradle"
    //true是调试模式,组件可以单独运行,false是正式打包模式
    //运行app的时候要把这里设置为false
    isDebug = false

    android = [
            compileSdk : 31,
            minSdk     : 23,
            targetSdk  : 31,
            versionCode: 10000,
            versionName: "1.0.0"
    ]

    applicationId = [
            "app": "com.k.zkt",
            "trade": "com.k.trade",
            "zkp": "com.k.zkp"
    ]

    //android中的lib
    library = [
            "corektx"         : "androidx.core:core-ktx:1.7.0",
            "appcompat"       : "androidx.appcompat:appcompat:1.3.0",
            "material"        : "com.google.android.material:material:1.4.0",
            "constraintlayout": "androidx.constraintlayout:constraintlayout:2.0.4",
            "junit"           : "junit:junit:4.13.2",
            "junitext"        : "androidx.test.ext:junit:1.1.3",
            "espressocore"    : "androidx.test.espresso:espresso-core:3.4.0",
    ]

    //第三方
    arouter = "com.alibaba:arouter-api:1.5.2"
    //哪个业务模块用到arouterCompiler,都需要单独依赖和添加AROUTER_MODULE_NAME
    arouterCompiler = "com.alibaba:arouter-compiler:1.5.2"
    litepal = "org.litepal.android:kotlin:3.0.0"
    gson = "com.google.code.gson:gson:2.8.6"
    mmkv = "com.tencent:mmkv-static:1.2.10"

    okhttp = "com.squareup.okhttp3:okhttp:3.14.9"
    retrofit = "com.squareup.retrofit2:retrofit:2.8.2"
    koinScope = "org.koin:koin-androidx-scope:2.1.5"
    koinViewmodel = "org.koin:koin-androidx-viewmodel:2.1.5"
    koinFragment = "org.koin:koin-androidx-fragment:2.1.5"
    koinExt = "org.koin:koin-androidx-ext:2.1.5"
    converterGson = "com.squareup.retrofit2:converter-gson:2.8.2"
    logging = "com.squareup.okhttp3:logging-interceptor:3.14.9"
    fastjson = "com.alibaba:fastjson:1.1.68.android"

    coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2"
    coroutinesAndroid = "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
    urlManager = "me.jessyan:retrofit-url-manager:1.4.0"

    baseAdapter = "com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4"
    aviLib = "com.wang.avi:library:2.1.3"
    finalLoadMore = "cn.finalteam.loadingviewfinal:loading-more-view:1.0.1"
    finalRefresh = "cn.finalteam.loadingviewfinal:swipe-refresh-layout:1.0.1"
    finalLoading = "cn.finalteam.loadingviewfinal:ultra-pull-to-refresh:1.0.1"
    listAdapter = "com.zhy:base-adapter:3.0.3"
    rvAdapter = "com.zhy:base-rvadapter:3.0.3"
    systembartint = "com.readystatesoftware.systembartint:systembartint:1.0.3"
    glance = "com.guolindev.glance:glance:1.1.0"
    eventbus = "org.greenrobot:eventbus:3.1.1"
    antifake = "com.snail:antifake:1.4"
    glide = "com.github.bumptech.glide:glide:4.8.0"

    lifecycleRuntime = "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0"
    lifecycleLivedata = "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
    lifecycleViewmodel = "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"

    zxingLite = "com.king.zxing:zxing-lite:1.1.2"
    backgroundLibrary = "com.github.JavaNoober.BackgroundLibrary:libraryx:1.7.3"
    fragmentKtx = "androidx.fragment:fragment-ktx:1.4.1"
    dsBridge = "com.github.wendux:DSBridge-Android:3.0-SNAPSHOT"
    livedatabus = "io.github.jeremyliao:live-event-bus-x:1.8.0"
    permissionx = "com.guolindev.permissionx:permissionx:1.6.4"
    materialDialogs = "com.afollestad.material-dialogs:core:0.9.6.0"

    navigationUi = "androidx.navigation:navigation-ui-ktx:2.3.5"
    navigationFragment = "androidx.navigation:navigation-fragment-ktx:2.3.5"
}

这边是把各个模块的build.gradle都抽取出来了

接下来是自定义的3个gradle:

app.gradle:主工程
bss.gradle:业务模块,可切换library和application
lib.gradle:library模块

app.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'org.jetbrains.kotlin.android'
def cfg = rootProject.ext
android {
    compileSdk cfg.android.compileSdk

    defaultConfig {
        applicationId cfg.applicationId.app
        minSdk cfg.android.minSdk
        targetSdk cfg.android.targetSdk
        versionCode cfg.android.versionCode
        versionName cfg.android.versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        //other
        //仅业务模块需要用到AROUTER
        kapt {
            arguments {
                arg("AROUTER_MODULE_NAME", project.getName())
            }
        }

        ndk {
            // 设置支持的SO库架构
            abiFilters "armeabi-v7a"
        }
    }

    buildTypes {
        debug {
            versionNameSuffix "-debug"
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        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'
    }

    buildFeatures {
        viewBinding true
    }


    flavorDimensions 'app'
    productFlavors {
        zkt {
            dimension 'app'
            applicationId 'com.k.zkt'
        }

    }
}
dependencies {
    kapt cfg.arouterCompiler
    implementation project(path: ':base:libBase')
    //不是调试模式的时候,trade和zkp才是library,才可以依赖
    if (!cfg.isDebug) {
        implementation project(path: ':bss:trade')
        implementation project(path: ':bss:zkp')
    }

}

bss.gradle

def cfg = rootProject.ext
if (cfg.isDebug) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'org.jetbrains.kotlin.android'
android {
    compileSdk cfg.android.compileSdk

    defaultConfig {
        minSdk cfg.android.minSdk
        targetSdk cfg.android.targetSdk
        versionCode cfg.android.versionCode
        versionName cfg.android.versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"

        //other
        //仅业务模块需要用到AROUTER
        kapt {
            arguments {
                arg("AROUTER_MODULE_NAME", project.getName())
            }
        }

        ndk {
            // 设置支持的SO库架构
            abiFilters "armeabi-v7a"
        }
    }

    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'
    }

    //other
    buildFeatures {
        viewBinding true
    }
    //业务组件需要动态切换AndroidManifest
    sourceSets {
        main {
            if (cfg.isDebug) {
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
            }
        }
    }

}




lib.gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'org.jetbrains.kotlin.android'
def cfg = rootProject.ext
android {
    compileSdk cfg.android.compileSdk

    defaultConfig {
        //library是没有applicationId,versionCode,versionName
        minSdk cfg.android.minSdk
        targetSdk cfg.android.targetSdk

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    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'
    }

    //other
    buildFeatures {
        viewBinding true
    }

}



因为都抽取出来了,所以各模块下的build.gradle里面直接引用即可
上面介绍了有这几个模块:

include ':app'
include ':bss:trade'
include ':bss:zkp'
include ':func:pay'
include ':func:share'
include ':base:libBase'
include ':base:libRouter'

我们来看下各模块的配置:

app下的build.gradle配置:
apply from: app
def cfg = rootProject.ext
:bss:trade下的build.gradle配置:
apply from: bss
def cfg = rootProject.ext
android {
    defaultConfig {
        if (cfg.isDebug) {
            applicationId cfg.applicationId.trade
        }
    }
}
dependencies {
    kapt cfg.arouterCompiler
    implementation project(path: ':base:libBase')
}
:bss:zkp下的build.gradle配置:
apply from: bss
def cfg = rootProject.ext
android {
    defaultConfig {
        if (cfg.isDebug) {
            applicationId cfg.applicationId.zkp
        }
    }
}
dependencies {
    kapt cfg.arouterCompiler
    implementation project(path: ':base:libBase')
}
:func:pay下的build.gradle配置:
apply from: lib
def cfg = rootProject.ext

dependencies {
    implementation project(':base:libBase')
}
:func:share下的build.gradle配置:
apply from: lib
def cfg = rootProject.ext

dependencies {
    implementation project(':base:libBase')
}
:base:libBase下的build.gradle配置:
apply from: lib
def cfg = rootProject.ext

dependencies {

    api cfg.library.corektx
    api cfg.library.appcompat
    api cfg.library.material
    api cfg.library.constraintlayout
    testImplementation  cfg.library.junit
    androidTestImplementation cfg.library.junitext
    androidTestImplementation cfg.library.espressocore

    api cfg.arouter
    //这里可以依赖其他的一些工具库,主app和其他业务模块只依赖liBase即可
    api project(path: ':base:libRouter')
    api(name: 'test', ext: 'aar')
    api cfg.litepal
    api cfg.gson
    api cfg.mmkv
    api cfg.okhttp
    api cfg.retrofit
    api cfg.koinScope
    api cfg.koinViewmodel
    api cfg.koinFragment
    api cfg.koinExt
    api cfg.converterGson
    api cfg.logging
    api cfg.fastjson
    api cfg.coroutinesCore
    api cfg.coroutinesAndroid
    api cfg.urlManager
    api cfg.baseAdapter
    api cfg.aviLib
    api cfg.finalLoadMore
    api cfg.finalRefresh
    api cfg.finalLoading
    api cfg.listAdapter
    api cfg.rvAdapter
    api cfg.systembartint
    api cfg.eventbus
    api cfg.antifake
    api cfg.glide
    api cfg.lifecycleRuntime
    api cfg.lifecycleLivedata
    api cfg.lifecycleViewmodel
    api cfg.zxingLite
    api cfg.backgroundLibrary
    api cfg.fragmentKtx
    api cfg.dsBridge
    api cfg.livedatabus
    api cfg.permissionx
    api cfg.materialDialogs
    api cfg.navigationUi
    api cfg.navigationFragment
    debugApi  cfg.glance
}
:base:libRouter下的build.gradle配置:
apply from: lib
def cfg = rootProject.ext

dependencies {

    api cfg.library.corektx
    api cfg.library.appcompat
    api cfg.library.material
    api cfg.library.constraintlayout
    testImplementation  cfg.library.junit
    androidTestImplementation cfg.library.junitext
    androidTestImplementation cfg.library.espressocore
}

需要注意的是arouterCompiler每个业务组件都要分别依赖
业务组件需要动态切换AndroidManifest,由于每个业务组件都需要切换,所以就直接抽取到bss.gradle中去了。
根据bss.gradle中配置的路径配置相应的manifest
在这里插入图片描述
debug下的:
debug下的是可以独立运行的,所以会有android.intent.category.LAUNCHER

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

    <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.Zkt">
        <activity
            android:name=".TradeActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

默认的

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

    <application>
        <activity
            android:name=".TradeActivity"
            android:exported="false"
            android:label=""
            android:screenOrientation="portrait" />
    </application>

</manifest>

其他业务组件同理,也是需要如上配置。
创建module的时候,如果需要加一个父级文件夹,name前多加一个即可在这里插入图片描述

Gradle 简单语法见官方:Gradle 提示与诀窍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哆啦A梦z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值