Android 架构 - 组件化 Componentization(Gradle版)

发布时间:2026/10/30 1:17:28
Android 架构 - 组件化 Componentization(Gradle版) 参考文章一、概念组件化是基于可重用目的对单个功能进行开发提升复用性降低耦合度。多个功能组件起来就是一个业务组件多个业务组件组合起来就是一个应用因此去除了模块间的耦合使得按业务划分的模块成了可单独运行的业务组件。组件化只是一定程度上的独立还是依附于整个项目中想完全独立详见插件化功能复用每个组件都是一个单独的功能可被不同的模块甚至不同的应用所使用。提高效率每个组件都是一个可单独编译运行的APP由于拆分使得代码量少调试起来快。协同开发组件之间相互独立使得不同的开发人员能专注于各自的功能开发互不影响。1.1 组件划分依赖关系是上层依赖下层修改频率是上层高于下层。对于业务组件由于存在页面跳转、方法调用、事件通信等问题需要使用路由通信其它层组件不存在耦合问题封装成 Library 即可。app壳应用的入口只依赖各业务组件不包含具体业务代码。将业务组件打包成一个APP做一些配置工作打包环境、签名、混淆等。业务组件module_XXX某个页面根据业务拆分的独立模块如主页模块、登录模块、商城模块。业务组件之间无直接关系通过路由进行通信。既可以作为 Application 单独编译运行调试又可作为 Library 集成到项目中。功能组件feature_XXX公共功能是对公用的功能进行封装与实现如网络请求、日志打印、地图、支付、广告。非必须层业务组件可以直接依赖基础组件去实现功能。基础组件lib_XXX最底层修改频率极低统一依赖配置和资源文件如引入第三方框架Retrofit、Glide、存放公用资源文件strings、drawable、自定义View、工具类Utils、实现路由ARouter。1.2 插件模式在组件的构建脚本 build.gradle 中指定指定为集成模式Library可以被其它组件调用指定为组件模式Application可以独立运行调试。com.android.application项目构建后输出 apk 包在调试时是一个应用能单独编译运行。com.android.library项目构建后输出 aar 包在打包时是一个库文件集成到项目中。//写法一和别的一起写 plugins { id com.android.library id org.jetbrains.kotlin.android } //写法二分开写 apply plugin: com.android.library1.3 创建组件File→New→New Module。业务组件需要调试选择【Phone Tablet】功能组件和基础组件只用来集成需要用到资源文件选【Android Library】纯代码选【Java or kotlin Library】。二、统一配置2.1 动态模式切换在 Project 的 build.gradle 中通过 ext{ } 添加全局变量 isDebug用来切换业务组件的模式true为组件模式会编译成Applicationfalse为集成模式会编译成Library同步一下后就可以在每个组件的 build.gradle 中读取并做相应的动态处理。见下方5.52.2 抽取组件 build.gradle 中相同的配置不同的 module 和 lib 组件都有很多重复的配置可分别抽取成 “commonModule.gradle” 和 “commonLib.gradle” 然后在具体的模组件中引入使用并删除已抽取的配置。2.2.1 抽取在项目上右键→New→File→命名为“commonModule.gradle”。由于自定义的 gradle 文件中无法使用 plugins{ }因此需要将插件一个个引入。commonModule提供组件模式的切换剔除各个 module 组件专有的 namespace、applicationId 属性。commonLib剔除各个 lib 组件专有的 namespace 属性。2.2.2 引入在每个组件的 build.gradle 中引入写在顶部。apply from: $rootDir/commonModule.gradle三、基础组件将一直作为 Library 存在app壳和所有的业务组件都依赖它主要封装公共功能网络请求、数据存储、自定义控件、工具类、版本管理和统一第三方依赖。3.1 创建 lib_common3.2 提供 BaseApplication其它组件都依赖于 lib_common因此在其中提供一个全局的 BaseApplication 供其它组件在代码中使用需要获取全局上下文的时候就使用这个BaseApplication所有资源的初始化也在这里。在集成模式Library中使用不需要注册在App壳和组件模式Application中需要自定义一个类继承 BaseApplication 后注册到 AndroidManifest 中使得从 BaseApplication 中获取的全局上下文生效还有初始化数据之用。组件所处的模式引入后如何使用集成模式Library直接使用 BaseApplication不是应用不需要注册。独立模式Application在 debug 文件夹中创建一个子类继承自 BaseApplication 然后注册到 debug 文件夹中的 AndroidManifest 中不需要使用自己定义的就注册为 BaseApplication。app壳创建一个子类继承自 BaseApplication 然后在 AndroidManifest 中注册不需要使用自己定义的就注册为 BaseApplication 。3.3 统一权限声明 AndroidManifest声明了项目中用到的所有权限 user-permission 和 uses-feature这样其它组件就无需在自己的 AndroidManifest.xm 声明自己要用到的权限了。3.4 统一第三方依赖 build.gradle统一所有组件中用到的第三方库和jar包具体写在 config.gradle 中再引入。使用 imlemntation 添加的依赖只对当前组件有效使用 api 添加的依赖对其上层组件同样有效这样依赖于基础组件的组件就不用再添加相同的依赖了。项目中某个组件会被其它组件重复依赖在集成构建应用时 Gradle 会剔除重复的 arr 包这样就不会存在好几份重复的代码了。而第三方库和我们的项目可能都依赖了相同的库例如 Glide 中也依赖了 OkHttp就会导致重复加载解决办法是找出相同的库根据组件名或包名排除。test替换不了引入的时候提示无法识别2024-01-044.5 公共类封装了项目中的 Base类、Utis工具类等公用的 Widget控件、业务组件中都用到的数据也应放在这里例如 SharedPreferences 和 DataBase 中的登录数据。4.6 公共资源将公共的 drawable、shape、layout、strings、colors、dimens、styles、theme 等资源文件放在这里提升复用性保证主题统一、避免文件名冲突。五、核心组件业务组件同理5.1 创建 module_core5.2 创建 debug 包在业务组件中创建 debug 包用于存放只在组件模式下使用的文件如程序入口 Launcher Activity、自定义Application在集成模式下会被剔除不参与打包见下方build.gradle中配置。在业务组件的 src/main/java 目录上右键→New→Package。不推荐在组件的其它层级上创建目录存放切换到Android视图不会显示5.3 自定义的 Application继承自 lib_common 中提供的 BaseApplication组件自定义的 Application 写在 debug 目录中在集成模式下剔除。别忘了在下方 debug 目录中的 AndroidManifest 中注册5.4 两份 AndroidManifest在组件模式下也会因为application标签配置、自定义Application 、指定启动入口Launcher Activity而在 AndroidManifest 中进行注册但在集成模式下打包到一起时存在重复和冲突桌面上好几个启动图标、只能注册一个自定义的Application、同一个权限无须多次申请。由于可以在 build.gradle 中动态指定组件的模式因此可以分别为两种模式加载不同的 AndroidManifest。组件模式下的 AndroidManifest 写在 debug 目录中在集成模式下剔除。将 AndroidStudio 为组件自动创建的 AndroidManifest 复制一份到 debug 目录对 manifest 标签添加 package 属性指定为业务组件的包名。 像单工程那样使用就行。修改自动创建的 AndroidManifest将 application 的属性保留了theme是方便组件中用到该主题的Activity不用每个都要单独设置 删除。module_core 不要删除程序入口app壳搬运的启动入口是这里其它业务组件删除程序入口只保留四大组件的注册对 manifest 标签添加 package 属性指定为组件的包名。5.5 修改 build.gradle在组件模式下才是一个应用因此需要动态配置组件模式和 applicationId。在 android 标签下使用 sourceSets 动态指定不同模式下加载的 AndroidManifest 文件并剔除 debug 包下的文件不参与集成模式下的打包。将版本替换成 config.gradle 中定义的。在 dependencies 中引入依赖。5.6 程序入口 LauncherActivity用于初始化数据后启动目标 Activity或给单Activity应用提供不需要可以省略因此写在 debug 目录下不用 setContentView()传入目标 Activity 需要的 Intent 参数即可。删除自动创建的 MainActivity。5.7 获取当前组件模式如果想在代码中通过获取当前组件的模式进行特定开发可以在业务组件 build.gradle 中的 defaultConfig 标签下进行配置会在 BuildConfig.java 类中生成对应的字段。5.8 专用资源重名问题 resourcePrefix打包可能出现资源文件重名的问题当前文件会覆盖被依赖模块中的添加前缀来规范每个组件中专用资源文件的命名。在 build.gradle 的 android 标签下添加 resourcePrefix core_此后资源文件都会爆红提醒要以 “core_” 为前缀命名不是报错依旧能编译运行。六、搬空app壳组件化需要一个空壳这个壳工程中不处理任何业务也没有Activity由它将各个业务模块组合起来构成一个完整的应用。6.1 搬运程序入口 MainActivity将 app 中的 MainActivity.class 和 activity_main.xml 剪切至 module_core 中。将 AndroidManifest 中的 MainActivity 注册包含程序入口也剪切至 module_core 中只保留 application 标签。6.2 搬运资源文件 res将 app 中的 整个 res 文件夹剪切至 lib_common 中。6.3 自定义的 Application必须继承自 lib_common 组件中的 BaseApplication如果app壳工程中无需自定义的Application 可以直接在 AndroidManifest 中声明为 BaseApplication因为只有这样在打包应用后才能让 BaseApplication 全局生效。可以在这里初始化项目中使用到的第三方SDK还可以在这里解决 Android 引用方法数不能超过 65535 的限制对崩溃事件的捕获和发送也可以在这里声明。6.4 修改 AndroidManifest官网合并清单说明application标签的属性都是在app壳配置的而其它组件也会有自己的清单在集成模式下最终会打包合并成一个文件需要解决属性重复在上面5.4中用于集成模式的AndroidManifest的application标签并不会进行配置但还是会配置theme分别对 app 的 manifest 和 application 添加如下代码。manifest 标签xmlns:toolshttp://schemas.android.com/toolsapplication 标签tools:replaceandroid:name,android:label,android:icon,android:theme,android:allowBackup6.5 修改 build.gradle应用的打包签名、buildTypes、defaultConfig都需要在这里配置而它的dependencies则需要根据 isDebug 的值分别依赖不同的组件在组件模式下app壳只需要依赖 lib_common 组件在集成模式下必须依赖所有声明的业务组件。当需要同时引入好几个组件时可以像“分组”一样一次性引入避免每次新建组件引入多个其他组件的时候出错。像多渠道打包、测试某几个固定组件协同时使用。将 defaultConfig 和 dependencies 下的配置移动 libs.versions.toml 中并引入只在组件模式下引入业务组件。七、对比app壳LibraryApplicationbuild.gradle插件模式com.android.applicationcom.android.librarycom.android.applicationapplicationId 属性有无组件模式下有集成模式下无。sourceSets 块无无组件模式下调用 debug 包中的自定义 AndroidManifest集成模式下调用 AndroidStudio 自动生成的并剔除 debug 包下的文件。dependencies 块组件模式下依赖所有业务组件集成模式下只依赖基础组件。基础组件添加所有组件用到的依赖功能组件依赖基础组件。业务组件依赖基础组件看需求依赖功能组件。AndroidManifestmanifest 标签添加 tools 属性避免合并冲突。设置 package 属性为自己包名。设置 package 属性为自己包名。application 标签配置并添加 replace 属性避免合并冲突。可以只配置theme属性避免每个Activity都要设置主题。组件模式下配置集成模式下可以只配置theme属性避免每个Activity都要设置主题。自定义Application继承 BaseApplication提供 BaseApplication继承 BaseApplication启动入口 LauncherActivity无设为 MainActivity设为 debug 包中的 LauncherActivity内容为空用来做初始化后跳转到 业务Activity。权限无四大组件无注册注册资源文件、公共类无基础组件存放都会用到的功能组件存放自己专用的。存放自己专用的八、组件间通信和跳转8.1 跳转路由表的设计8.2 通信服务接口的设计组件化后使得代码隔离访问不到其它组件中的代码通过接口解耦的方式调用方不需要关心服务是谁提供的提供方不需要关心谁在何时调用服务。对于接口文件的存放地需要考虑是否去中心化。统一存放小型项目分开存放大型项目优点管理方便每个接口可使用不同的版本并且使用方只需要依赖特定的接口。缺点不利于需要跨APP复用的项目所有接口对应一个组件版本不能支持单一接口使用不同版本的组件并且使用方可能会引入大量无用的接口依赖。会创建更多的组件组件数量会增加依赖查找的耗时。实现可以用一个专门的组件 lib_router 来存放所有组件路由接口来避免 lib_common 变得臃肿每个组件都依赖该模块实现自己业务的接口并提供路由。module_login 对应有一个 export_login使用一个组件都要添加两个依赖。可以把 export_login 当作 module_login 组件的协议通过它可以知道能和 module_login 做些什么交互包含了服务接口和路由表减少协同开发沟通成本。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询