Android 架构 - 组件化 Componentization

这篇具有很好参考价值的文章主要介绍了Android 架构 - 组件化 Componentization。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概念

组件化是基于可重用目的,对单个功能进行开发,提升复用性降低耦合度。多个功能组件起来就是一个业务组件,多个业务组件组合起来就是一个应用,因此去除了模块间的耦合,使得按业务划分的模块成了可单独运行的业务组件。(组件化只是一定程度上的独立,还是依附于整个项目中,想完全独立详见插件化)

  • 功能复用:每个组件都是一个单独的功能,可被不同的模块甚至不同的应用所使用。
  • 提高效率:每个组件都是一个可单独编译运行的APP,由于拆分使得代码量少,调试起来快。
  • 协同开发:组件之间相互独立,使得不同的开发人员能专注于各自的功能开发互不影响。

1.1 需要考虑的问题

组件分层、切换模式按需编译、组件通信(路由框架)、组件生命周期(组件在应用中存在的时间,组件是否可以按照需求动态使用,涉及到组件的加载卸载等管理问题。)

1.2 插件模式

在组件的构建脚本 build.gradle 中指定,指定为集成模式(Library)可以被其它组件调用,指定为组件模式(Application)可以独立运行调试。

com.android.application 项目构建后输出 apk 包,在调试时是一个应用能单独编译运行。
com.android.library 项目构建后输出 aar 包,在打包时是一个库文件集成到项目中。
com.android.test 配置一个 Android Test 工程。
//写法一(和别的一起写)
plugins {
    id 'com.android.library'
    id 'org.jetbrains.kotlin.android'
}
//写法二(分开写)
apply plugin: 'com.android.library'

1.3 创建组件

File→New→New Module。业务组件需要调试选择【Phone & Tablet】,功能组件和基础组件只用来集成,需要用到资源文件选【Android Library】,纯代码选【Java or kotlin Library】。

Android 架构 - 组件化 Componentization,架构,android

二、结构划分

Android 架构 - 组件化 Componentization,架构,android

依赖关系是上层依赖下层,修改频率是上层高于下层。对于业务组件由于存在页面跳转、方法调用、事件通信等问题需要使用路由通信,其它层组件不存在耦合问题封装成 Library 即可。

app壳工程 应用的入口:将业务组件打包成一个APP,做一些配置工作。(打包环境、签名、混淆等)
业务组件 某个页面(主页、消息、商城):业务组件之间无直接关系,通过路由进行通信。既可以作为 Application 单独编译运行调试,又可作为 Library 集成到项目中。
功能组件 公共功能(地图、分享、广告):是对公用的功能进行抽取,非必须层,业务组件可以直接依赖基础组件去实现功能。
基础组件 统一依赖配置和资源文件:引入第三方框架(Retrofit、Glide)、存放公用资源文件(strings、drawable、自定义View、工具类Utils)、实现路由(ARouter)。修改频率极低。

三、统一配置

3.1 模式切换

在 Program 的 build.gradle 中通过 ext{ } 添加全局变量 isDebug,用来切换业务组件的模式(true为组件模式会编译成Application,false为集成模式会编译成Library),同步一下后就可以在每个组件的 build.gradle 中读取并做相应的动态处理。(见下方5.5)

Android 架构 - 组件化 Componentization,架构,android

3.2 规范一次引入多个组件

当需要同时引入好几个组件时,可以像“分组”一样一次性引入,避免每次新建组件引入多个其他组件的时候出错。像多渠道打包、测试某几个固定组件协同时使用。

Android 架构 - 组件化 Componentization,架构,android​​​​

3.3 依赖管理 Verison Catalogs

此前会将依赖项定义在自定义的 config.gradle 中然后在 Program 的 build.gradle 中引入,这样不支持点击跳转和更新提示,且更新依赖会重构整个项目。

在项目上右键→New→File→命名为“libs.versions.toml”,然后在 settings.gradle 中的 <dependencyResolutionManagement> 标签下使用 <versionCatalogs> 引入所创建的文件。

versions 声明依赖项和插件的版本,然后引用这些变量。
libraries 声明依赖项的别名
bundles 声明依赖项的组名
plugins 声明插件

Android 架构 - 组件化 Componentization,架构,android

3.4.1 依赖项

原来

dependencies {
    implementation 'androidx.core:core-ktx:1.9.0'
}

现在

[versions]
demo = "1.9.0"

[libraries]
#写法一
demo-compiler1 = "com.example:demo-compiler:1.9.0"
#写法二
demo-compiler2 = { module = "com.example:demo-compiler", version = "1.9.0" }
#写法三
demo-compiler3 = { module = "com.example:demo-compiler", version.ref = "1.9.0" }
#写法四
demo-compiler4 = { group = "com.example", name = "demo-compiler", version = "demo" }
#写法五
demo-compiler5 = { group = "com.example", name = "demo-compiler", version.ref = "demo" }
dependencies {
    #只有 libraries 中的属性可以直接调用
    #如果其它节点中有重名的,调用起来是 libs.versions.demo
    implementation libs.demo.compiler
}

3.4.2 插件

原来

// Program的build.gradle.kts中
plugins {
   id("com.android.application") version "7.4.1" apply false
}

// Module的build.gradle.kts中
plugins {
   id("com.android.application")
}

现在

[versions]
androidGradlePlugin = "7.4.1"

[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
// Program的build.gradle.kts中
plugins {
   alias(libs.plugins.android.application) apply false
}

// Module的build.gradle.kts中
plugins {
   alias(libs.plugins.android.application)
}

3.4 抽取组件 build.gradle 中相同的配置

不同的 module 和 lib 组件都有很多重复的配置,可分别抽取成 “commonModule.gradle” 和 “commonLib.gradle” 然后在具体的模组件中引入使用,并删除已抽取的配置。

 在项目上右键→New→File→命名为“commonModule.gradle”。

  • 由于自定义的 gradle 文件中无法使用 plugins{ },因此需要将插件一个个引入。
  • commonModule:提供组件模式的切换,剔除各个 module 组件专有的 namespace、applicationId 属性。
  • commonLib:剔除各个 lib 组件专有的 namespace 属性。

Android 架构 - 组件化 Componentization,架构,android

四、基础组件

将一直作为 Library 存在,app壳和所有的业务组件都依赖它,主要封装公共功能(网络请求、数据存储、自定义控件、工具类)、版本管理和统一第三方依赖。

4.1 创建 lib_common

Android 架构 - 组件化 Componentization,架构,android

4.2 提供 BaseApplication

其它组件都依赖于 lib_common,因此在其中提供一个全局的 BaseApplication 供其它组件在代码中使用。在集成模式(Library)中使用不需要注册,在App壳和组件模式(Application)中需要注册到 AndroidManifest 中使得从 BaseApplication 中获取的全局上下文生效,还有初始化数据之用。

  • 对于集成模式(Library):直接使用 BaseApplication,不是应用不需要注册。
  • 对于app壳:创建一个子类继承自 BaseApplication 然后在 AndroidManifest 中注册。(不需要使用自己定义的就注册为 BaseApplication)
  • 对于组件模式(Application):在 debug 文件夹中创建一个子类继承自 BaseApplication 然后注册到 debug 文件夹中的 AndroidManifest 中。(不需要使用自己定义的就注册为 BaseApplication) 

Android 架构 - 组件化 Componentization,架构,android

4.3 统一权限声明 AndroidManifest

声明了项目中用到的所有权限 user-permission 和 uses-feature,这样其它组件就无需在自己的 AndroidManifest.xm 声明自己要用到的权限了。

 Android 架构 - 组件化 Componentization,架构,android

4.4 统一第三方依赖 build.gradle

        统一所有组件中用到的第三方库和jar包,具体写在 config.gradle 中再引入。使用 imlemntation 添加的依赖只对当前组件有效,使用 api 添加的依赖对其上层组件同样有效,这样依赖于基础组件的组件就不用再添加相同的依赖了。

        项目中某个组件会被其它组件重复依赖,在集成构建应用时 Gradle 会剔除重复的 arr 包,这样就不会存在好几份重复的代码了。而第三方库和我们的项目可能都依赖了相同的库(例如 Glide 中也依赖了 OkHttp)就会导致重复加载,解决办法是找出相同的库根据组件名或包名排除。

  • test替换不了,引入的时候提示无法识别(2024-01-04) 

Android 架构 - 组件化 Componentization,架构,android

4.5 公共类

封装了项目中的 Base类、Utis工具类等,公用的 Widget控件、业务组件中都用到的数据也应放在这里(例如 SharedPreferences 和 DataBase 中的登录数据)。

4.6 公共资源

将公共的 drawable、shape、layout、strings、colors、dimens、styles、theme 等资源文件放在这里,提升复用性,保证主题统一、避免文件名冲突。

五、核心组件(业务组件同理)

5.1 创建 module_core

Android 架构 - 组件化 Componentization,架构,android

5.2 创建 debug 包

在业务组件中创建 debug 包,用于存放只在组件模式下使用的文件(如程序入口 Launcher Activity、自定义Application),在集成模式下会被剔除不参与打包(见下方build.gradle中配置)。

在业务组件的 src/main/java 目录上右键→New→Package。(不推荐在组件的其它层级上创建目录存放,切换到Android视图不会显示)

Android 架构 - 组件化 Componentization,架构,android

5.3 自定义的 Application

继承自 lib_common 中提供的 BaseApplication,组件自定义的 Application 写在 debug 目录中,在集成模式下剔除。(别忘了在下方 debug 目录中的 AndroidManifest 中注册)

Android 架构 - 组件化 Componentization,架构,android

5.4 两份 AndroidManifest

        在组件模式下,也会因为<application>标签配置、自定义Application 、指定启动入口(Launcher Activity)而在 AndroidManifest 中进行注册,但在集成模式下打包到一起时存在重复和冲突(桌面上好几个启动图标、只能注册一个自定义的Application、同一个权限无须多次申请)。

        由于可以在 build.gradle 中动态指定组件的模式,因此可以分别为两种模式加载不同的 AndroidManifest。组件模式下的 AndroidManifest 写在 debug 目录中,在集成模式下剔除。

  1. 将 AndroidStudio 为组件自动创建的 AndroidManifest 复制一份到 debug 目录,对 <manifest> 标签添加 package 属性指定为业务组件的包名。 像单工程那样使用就行。
  2. 修改自动创建的 AndroidManifest,将 <application> 的属性(保留了theme是方便组件中用到该主题的Activity不用每个都要单独设置) 删除。module_core 不要删除程序入口(app壳搬运的启动入口是这里),其它业务组件删除程序入口只保留四大组件的注册,对 <manifest> 标签添加 package 属性指定为组件的包名。

Android 架构 - 组件化 Componentization,架构,android

5.5 修改 build.gradle

  1. 在组件模式下才是一个应用,因此需要动态配置组件模式和 applicationId。
  2. 在 <android> 标签下使用 <sourceSets> 动态指定不同模式下加载的 AndroidManifest 文件,并剔除 debug 包下的文件不参与集成模式下的打包。
  3. 将版本替换成 config.gradle 中定义的。
  4. 在 <dependencies> 中引入依赖。

Android 架构 - 组件化 Componentization,架构,android

5.6 程序入口 LauncherActivity

用于初始化数据后启动目标 Activity(不需要可以省略),因此写在 debug 目录下,不用 setContentView(),传入目标 Activity 需要的 Intent 参数即可。

Android 架构 - 组件化 Componentization,架构,android

5.7 获取当前组件模式

如果想在代码中通过获取当前组件的模式进行特定开发,可以在业务组件 build.gradle 中的 <defaultConfig> 标签下进行配置,会在 BuildConfig.java 类中生成对应的字段。

Android 架构 - 组件化 Componentization,架构,android

5.8 专用资源重名问题 resourcePrefix

打包可能出现资源文件重名的问题(当前文件会覆盖被依赖模块中的),添加前缀来规范每个组件中专用资源文件的命名。

在 build.gradle 的 <android> 标签下添加 resourcePrefix "core_",此后资源文件都会爆红提醒要以 “core_” 为前缀命名(不是报错,依旧能编译运行)。

Android 架构 - 组件化 Componentization,架构,android

六、搬空app壳

组件化需要一个空壳,这个壳工程中不处理任何业务,也没有Activity,由它将各个业务模块组合起来构成一个完整的应用。

6.1 搬运程序入口 MainActivity

  1. 将 app 中的 MainActivity.class 和 activity_main.xml 剪切至 module_core 中。
  2. 将 AndroidManifest 中的 MainActivity 注册(包含程序入口)也剪切至 module_core 中只保留 <application> 标签。

Android 架构 - 组件化 Componentization,架构,android

6.2 搬运资源文件 res

将 app 中的 整个 res 文件夹剪切至 lib_common 中。

6.3 自定义的 Application

必须继承自 lib_common 组件中的 BaseApplication(如果app壳工程中无需自定义的Application 可以直接在 AndroidManifest 中声明为 BaseApplication),因为只有这样在打包应用后才能让 BaseApplication 全局生效。

  • 可以在这里初始化项目中使用到的第三方SDK,还可以在这里解决 Android 引用方法数不能超过 65535 的限制,对崩溃事件的捕获和发送也可以在这里声明。 

Android 架构 - 组件化 Componentization,架构,android

6.4 修改 AndroidManifest

<application>标签的属性都是在app壳配置的,而其它组件也会有自己的清单,在集成模式下最终会打包合并成一个文件,需要解决属性重复(在上面5.4中用于集成模式的AndroidManifest的<application>标签并不会进行配置,但还是会配置theme),分别对 app 的 <manifest> 和 <application> 添加如下代码。

manifest 标签 xmlns:tools="http://schemas.android.com/tools"
application 标签 tools:replace="android:name,android:label,android:icon,android:theme,android:allowBackup"

Android 架构 - 组件化 Componentization,架构,android

6.5 修改 build.gradle

应用的打包签名、buildTypes、defaultConfig都需要在这里配置,而它的dependencies则需要根据 isDebug 的值分别依赖不同的组件,在组件模式下app壳只需要依赖 lib_common 组件,在集成模式下必须依赖所有声明的业务组件。

将 <defaultConfig> 和 <dependencies> 下的配置移动到 config.gradle 和 libs.versions.toml 中并引入,只在组件模式下引入业务组件。

Android 架构 - 组件化 Componentization,架构,android

七、对比

app壳 Library Application
build.gradle 插件模式 com.android.application com.android.library com.android.application
applicationId 属性 组件模式下有,集成模式下无。
sourceSets 块 组件模式下调用 debug 包中的自定义 AndroidManifest,集成模式下调用 AndroidStudio 自动生成的并剔除 debug 包下的文件。
dependencies 块

组件模式下依赖所有业务组件,集成模式下只依赖基础组件。文章来源地址https://www.toymoban.com/news/detail-794153.html

基础组件添加所有组件用到的依赖,功能组件依赖基础组件。 依赖基础组件,看需求依赖公共业务组件。
AndroidManifest <manifest> 标签 添加 tools 属性避免合并冲突。 设置 package 属性为自己包名。 设置 package 属性为自己包名。
<application> 标签 配置并添加 replace 属性避免合并冲突。 可以只配置theme属性避免每个Activity都要设置主题。 组件模式下配置,继承模式下可以只配置theme属性避免每个Activity都要设置主题。
自定义Application 继承 BaseApplication 提供 BaseApplication 继承 BaseApplication
启动入口 LauncherActivity 设为 MainActivity 设为 debug 包中的 LauncherActivity,内容为空用来做初始化后跳转到 业务Activity。
权限
四大组件 注册 注册
资源文件、公共类 基础组件存放都会用到的,功能组件存放自己专用的。 存放自己专用的

到了这里,关于Android 架构 - 组件化 Componentization的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Android】从零搭建组件化项目

    组件化系列文章介绍的内容稍微多了点,本着研究透这玩意的精神,从组件化的简介开始说起。 什么是组件化? 将多个功能模板拆分、重组的过程。 为什么要使用组件化? 1、加快编译速度,提高开发效率,增强可维护性、移植性。 2、高内聚(软件模块是由相关性很强的代

    2024年02月15日
    浏览(39)
  • Android GreenDao 使用全面讲解,Android组件化入门

    5. 在多个线程中使用QueryBuilder 如果在多个线程中使用查询,则必须调用 forCurrentThread ()以获取当前线程的Query实例。Query的对象实例绑定到构建查询的拥有线程。 这使您可以安全地在Query对象上设置参数,而其他线程不会干扰。如果其他线程尝试在查询上设置参数或执行绑

    2024年04月27日
    浏览(42)
  • Android AGP8.1.0组件化初探

    前面两篇完成了从AGP4.2到 AGP8.1.0的升级,本文是由于有哥们留言说在AGP8.0中使用ARouter组件化有问题,于是趁休息时间尝试了一下,写了几个demo,发现都没有问题,跳转和传值都是正常的,这里我也是直接从groovy转换成version-catalogs的依赖方式,由于之前升级过,所以这次很顺

    2024年02月10日
    浏览(32)
  • Android彻底组件化—UI跳转升级改造

    (2)host对应的是share。在组件化框架中,每个组件对应一个唯一的host,例如分享组件的host就是share,读书组件的host是reader等等。 host是路由分发的第一级,根据host可以定位到每个组件。 host还可以对所有的路由URL进行一个分组,只有调用到该分组的路由的时候,组内的路由

    2024年04月16日
    浏览(26)
  • Android学习之路(23)组件化框架ARouter的使用

    支持直接解析标准URL进行跳转,并自动注入参数到目标页面中 支持多模块工程使用 支持添加多个拦截器,自定义拦截顺序 支持依赖注入,可单独作为依赖注入框架使用 支持InstantRun 支持MultiDex (Google方案) 映射关系按组分类、多级管理,按需初始化 支持用户指定全局降级与局

    2024年01月22日
    浏览(70)
  • Android学习之路(22) 从模块化到组件化

    Android 应用项目 , 都存在一个应用模块 ( Application Module ) , 在 build.gradle 构建脚本中 , 第一个插件配置 com.android.application , 表明 该 Module 编译打包后的输出是 APK 安装包 ; 该项目可以直接运行 ; 如果在 build.gradle 配置的是 com.android.library 插件 , 那么 编译 Module 打包后输出的是 a

    2024年01月22日
    浏览(38)
  • 现代化 Android 开发:组件化与模块化的抉择

    作者:古哥E下 项目初始的时候,一般都是使用一个分层架构,接入各种框架,然后就写业务代码。但如果项目慢慢变大,那就会出现很多项目管理的问题,诸如: 1.代码复用与抽象问题 2.编译速度问题 3.版本迭代速度问题 所以组件化、模块化、动态化、插件化、跨平台等各

    2024年02月11日
    浏览(47)
  • Android技术栈(二)组件化改造,目前最稳定和高效的UI适配方案

    .build(PR.navi.navi) .navigation(); 而 Activity 则不需要,它会立即显示 ARouter.getInstance() .build(PR.navi.navi) //还可以设置参数,ARouter会帮你存在Bundle中 .withString(“pathId”,UUID.randomUUID().toString()) //Activity 或 Context .navigation(this); navi 模块是典型的业务逻辑模块,这里你可导入一些只有这个模块才

    2024年03月24日
    浏览(37)
  • 一篇读懂 Android 开发中模块化、组件化、插件化和热修复

    网上关于 “Android 开发\\\" 的文章很多,我本人学习 Android 开发的过程也借鉴了网上先辈们的文章;但大多数文章都从底层的细枝末节开始讲述,由下而上给人一种这门技术“博大精深”望而生畏的感觉;而我写这篇文章的初衷就是由上而下,希望别人在阅读的过程中能够觉得

    2023年04月08日
    浏览(30)
  • 组件化开发之如何封装组件-react

    组件是构建用户界面的基本单元,它是一个独立的、可重用的、可组合的代码单元,用于表示UI的一部分。 人话:当谈论组件时,就像在搭积木一样,每个组件都是一个 独立的、可以重复使用 的代码块,用来构建网页或应用的各个部分。比如界面的布局,像按钮、文本输入

    2024年02月11日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包