【Android】项目的组件化搭建

介绍

模块化和组件化

模块化:

将一个程序按照功能做拆分,分成独立的模块,每个模块只包含和它功能相关的内容;

组件化:
  1. 组件对应单独的功能组件,比如:登录组件,支付组件;
  2. 每个组件都可以单独编译开发,抽出SDK发布;
  3. 一个模块包含了一个或多个组件;

优势:

  1. 减少了编译时间:每个业务功能,可以独立编译运行;
  2. 减少了沟通成本,一定程度上减少了个人开发风格的差异;
  3. 解耦:将一个app分成多个模块,一个模块就是一个组件;
  4. 复用:可以新项目微调/直接使用;

组件分层

  1. 基础组件:
  1. 基础公共模块,最底层的;
  2. 网络请求框架,图片加载框架等主流的第三方库;
  3. SDK;
  1. common组件
  1. 支持业务/功能组件,依赖基础组件;
  2. 业务组件和功能组件只依赖此组件俩获取基础能力;
  1. 功能组件
  1. 依赖基础组件层;
  2. 对一些公用的功能业务进行封装实现;
  1. 业务组件
  1. 依赖基础组件层和一些公用功能组件;
  2. 各组件不通信,得通过路由通信;
  3. 业务组件可以在library和application之间切换,但是最后打包时必须是library ;
  1. 主工程
  1. 依赖各业务组件;
  2. 除了全局的配置和主Activity之外,不包含业务代码,是应用的入口;

组件化项目的搭建

抽离共用的build.gradle版本数据

每个模块独立开发,可能会遇到版本信息不一致,这时我们需要统一管理项目的依赖库;

怎么管理:

  1. 创建config.gradle文件:一些sdk版本,依赖库;
java 复制代码
ext{
    //ext是指额外的属性和变量,整个构建脚本中重复使用和共享;
    isDebug = false;
    android = [
            compileSdkVersion: 33,  //编译app的最低SDK版本
            minSdkVersion    : 32,//运行app的最低SDK版本
            targetSdkVersion : 33,//目标pp的的最低SDK版本
            versionCode      : 1,//指定可以识别该app数字
            versionName      : "1.0"//编指定可以识别该app的字符
    ]
    //每个模块的application地址
    applicationId = {
        //  "app"  : "com.example.dome",
    }
    //常用库的依赖
    library = [
            "appcompat"       : "androidx.appcompat:appcompat:1.6.1",
            "material"        : "com.google.android.material:material:1.5.0",
            "constraintlayout": "androidx.constraintlayout:constraintlayout:2.1.4"
    ]
//第三方库
    libGson = "com.google.code.gson:gson:2.8.6"
    libARouter = "com.alibaba:arouter-api:1.5.2"
    libARouterCompiler = "com.alibaba:arouter-compiler:1.5.2"

}
  1. 让总的build.gradle去apply它;
java 复制代码
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library) apply false
}
apply from:"config.gradle"
  1. 以后的版本修改改config.gradle;

创建基础层

  1. 建立一个Module,然后可以放在一个包下统一管理:

  2. 修改该模块下的Build.gradle,主要要和config.gradle搭配使用;

java 复制代码
plugins {
    alias(libs.plugins.android.library)

}
def swy = rootProject.ext
android {
    namespace swy.applicationId.libbase
    compileSdk swy.android.compileSdkVersion

    defaultConfig {
        minSdk swy.android.minSdkVersion

        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_11
        targetCompatibility JavaVersion.VERSION_11
    }
}

dependencies {
    api swy.library.appcompat
    api swy.library.material
    api swy.library.constraintlayout

    //等价于
    library.forEach {k,v->implementation v}

    api swy.libGson

    implementation libs.appcompat
    implementation libs.material
    testImplementation libs.junit
    androidTestImplementation libs.ext.junit
    androidTestImplementation libs.espresso.core
}
  1. 要获得项目根目录的引用,得到ext ,使用公用依赖等;
  2. 使用了def , 减少了rootProject.ext的次数,提高性能;
  3. 改动:
  1. 引入rootProject.ext;
  2. 改变命名空间:
    namespace swy.applicationId.libbase
  3. 使用android的[]下的一些版本;
  4. 依赖:添加公用依赖和第三方库依赖;
  1. api的方式引用:a模块导入依赖,b模块通过api 可以导入a导入依赖;

创建组件层

  1. 创建Module: 需要注意的点有:我们需要在我们组件模块的包名前加上module(或者其他的),否则可能包导致冲突;这次我们需要点第一个;使用application插件;
  2. 创建debug模块,移动AM到debug模块中;

打包模式下不需要其他的活动清单,对里面内容改动:

java 复制代码
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
       >
        <activity
            android:name=".MainActivity"
            android:exported="true">

        </activity>
    </application>

</manifest>

这样做是因为,如果是单独调试,那么需要一个启动页AM, 但是如果是打包的话,合并就会有多个启动页,这个时候就不需要其他的活动清单;

  1. 关于build.gradle的变动:
java 复制代码
if(rootProject.ext.isDebug){
    apply plugin: 'com.android.application'
}
else{
    apply plugin: 'com.android.library'
}
def swy = rootProject.ext
android {
    namespace swy.applicationId.login
    compileSdk swy.android.compileSdkVersion

    defaultConfig {
        if(swy.isDebug){
            applicationId swy.applicationId.login
        }
        minSdk swy.android.minSdkVersion
        targetSdk swy.android.targetSdkVersion
        versionCode swy.android.versionCode
        versionName swy.android.versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
    sourceSets{
        main{
            if(swy.isDebug){
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            }
            else{
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java{
                    exclude "**/debug/**"
                }
            }
        }
    }
}

dependencies {

    implementation project(':modulesBase:libBase')

    implementation libs.appcompat
    implementation libs.material
    implementation libs.activity
    implementation libs.constraintlayout
    testImplementation libs.junit
    androidTestImplementation libs.ext.junit
    androidTestImplementation libs.espresso.core
}

关于变动想说明以下几点:

  1. 为了达到调试时可以作为单独运行,打包时就会变成一个arr文件配合app使用,这时:
java 复制代码
if(rootProject.ext.isDebug){
    apply plugin: 'com.android.application'
}
else{
    apply plugin: 'com.android.library'
}
  1. 判断是不是出于调试模式,如果是的话, 'com.android.application'
    如果不是apply plugin: 'com.android.library'
  2. applicationId : app运行需要这个标识符来启动login的运行,所以如果是调试模式,我们需要定义;
  3. sourceSets:用于指定安卓项目的源集,用于构建app所需要的项目源代码或者资源等的配置;
  4. Main: sourceSets内的源集;
  5. 条件语句:根据不同模式来决定使用哪一个清单文件;
  6. "/debug/" : **表示匹配任意数量的目录,总的表示移除任何存在debug的路径
  7. 引入基础模块: implementation project(':modulesBase:libBase')

搭建App层

java 复制代码
app的build.gradle:
plugins {
    alias(libs.plugins.android.application)
}
def swy  = rootProject.ext
android {
    namespace swy.applicationId.app
    compileSdk swy.android.compileSdkVersion

    defaultConfig {
        if(swy.isDebug){
            applicationId swy.applicationId.login
        }
        minSdk swy.android.minSdkVersion
        targetSdk swy.android.targetSdkVersion
        versionCode swy.android.versionCode
        versionName swy.android.versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        buildConfigField("boolean","isDebug",String.valueOf(isDebug))
    }
buildFeatures{
    buildConfig true
}
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
}

dependencies {


    implementation project(':modulesBase:libBase')
    if(!swy.isDebug){
        implementation project(":modulesCore:login")
    }
    testImplementation libs.junit
    androidTestImplementation libs.ext.junit
    androidTestImplementation libs.espresso.core
}
  1. buildConfigField("boolean","isDebug",String.valueOf(isDebug))
    它可以把gradle数据映射到Java类里面,可以在Java类中使用gradle数据;
java 复制代码
 if(!swy.isDebug){
        implementation project(":modulesCore:login")
    }
  1. 启动 buildConfigField功能
java 复制代码
buildFeatures{
    buildConfig true
}

搭建成果

如果Debug是tue:

如果Debug是false:

改:把所有的swy.isDebug改成isDebug.toBoolean()

在gradle.properties中的;

isDebug = false 修改isDebug值;

相关推荐
aqi002 小时前
FFmpeg开发笔记(九十四)基于Kotlin的国产开源推拉流框架anyRTC
android·ffmpeg·kotlin·音视频·直播·流媒体
马 孔 多 在下雨2 小时前
Android 组件化开发基础实践
android
技术摆渡人2 小时前
Android 系统技术探索(2)构建大脑(System Services & PMS)
android
tealcwu2 小时前
【Unity实战】如何使用VS Code在真实Android设备上调试 Unity应用
android·unity·游戏引擎
鹏多多3 小时前
flutter-屏幕自适应插件flutter_screenutil教程全指南
android·前端·flutter
小龙报3 小时前
【C语言初阶】动态内存分配实战指南:C 语言 4 大函数使用 + 经典笔试题 + 柔性数组优势与内存区域
android·c语言·开发语言·数据结构·c++·算法·visual studio
小龙报3 小时前
【算法通关指南:算法基础篇(三)】一维差分专题:1.【模板】差分 2.海底高铁
android·c语言·数据结构·c++·算法·leetcode·visual studio
TeleostNaCl3 小时前
使用 Android Jetpack 中的 Startup 组件快速实现组件初始化逻辑与主模块解耦
android·经验分享·android jetpack·androidx·android runtime·jetpack android
恋猫de小郭3 小时前
让 AI 用 Flutter 实现了猗窝座的破坏杀·罗针动画,这个过程如何驯服 AI
android·前端·flutter