写点什么

Android 笔记:Android- 组件化方案探索与思考

用户头像
Android架构
关注
发布于: 16 小时前

组件化初衷

  • APP 版本不断的迭代,新功能的不断增加,业务也会变的越来越复杂,维护成本高。

  • 业务耦合度高,代码越来越臃肿,团队内部多人协作开发困难。

  • Android 项目在编译代码的时候电脑会非常卡,又因为单一工程下代码耦合严重,每修改一处代码后都要重新编译打包测试,导致非常耗时。

  • 方便单元测试,改动单独一个业务模块,不需要着重于关注其他模块被影响。

什么是组件化

组件化就是将一个 app 分成多个 Module,如下图,每个 Module 都是一个组件(也可以是一个基础库供组件依赖),开发的过程中我们可以单独调试部分组件,组件间不需要互相依赖,但可以相互调用,最终发布的时候所有组件以 lib 的形式被主 app 工程依赖并打包成一个 apk。


组件化优势

  • 组件化就是将通用模块独立出来,统一管理,以提高复用,将页面拆分为粒度更小的组件,组件内部除了包含 UI 实现,还包含数据层和逻辑层。

  • 每个工程都可以独立编译、加快编译速度,独立打包。

  • 每个工程内部的修改,不会影响其他工程。

  • 业务库工程可以快速拆分出来,集成到其他 App 中。

  • 迭代频繁的业务模块采用组件方式,业务线研发可以互不干扰、提升协作效率,并控制产品质量,加强稳定性。

  • 并行开发,团队成员只关注自己的开发的小模块,降低耦合性,后期维护方便等。

指导思想

  • 组件拆分:将一个 project 划分成业务组件、基础组件、路由组件。其中业务组件是相互隔离的,可以单独调试,基础组件提供业务组件所公用的功能,路由组件为业务组件之间通信提供支持。

  • 组件隔离:业务组件之间的隔离,可以单独调试。

  • 核心法则:编译期隔离,运行期按需依赖。

依赖关系

![](//upload-images.jianshu.io/upload_images/6970555-ac31a268195c0921?imageMogr2/auto-orient/strip%7Cim


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ageView2/2/w/1000/format/webp)

组件化需要考虑的问题

  • 模式切换:如何使得 APP 在单独调试跟整体调试自由切换

  • 资源冲突:当我们创建了多个 Module 的时候,如何解决相同资源文件名合并的冲突

  • 依赖关系:多个 Module 之间如何引用一些共同的 library 以及工具类

  • 组件通信:组件化之后,Module 之间是相互隔离的,如何进行 UI 跳转以及方法调用

  • 入口参数:我们知道组件之间是有联系的,所以在单独调试的时候如何拿到其它的 Module 传递过来的参数

组件化后项目结构如下图

理论说了那么多,下面开始撸代码

实现步骤

1、全局设置 Gradle,每一个业务 Module 需要的版本都定义在这里方便后期维护多个 Module 版本号


ext {// Sdk and toolsminSdkVersion = 16targetSdkVersion = 26compileSdkVersion = 26buildToolsVersion = '26.0.2'supportLibraryVersion = '26.1.0'


// App dependenciesaRouter = '1.2.2'leakcanaryVersion = '1.3'glideVersion = '3.7.0'}


####每个业务 Module 编译依赖版本 compileSdkVersion rootProject.ext.compileSdkVersionbuildToolsVersion rootProject.ext.buildToolsVersionminSdkVersion rootProject.ext.minSdkVersiontargetSdkVersion rootProject.ext.targetSdkVersion


2、模式切换


组件化后的每一个业务的 module 都可以是一个单独的 APP(isModuleRun=false), release 包的时候各个业务 module 作为 lib 依赖,这里完全由一个变量控制,在根项目 gradle.properties里面的 isModuleRun=true


isModuleRun 状态不同,加载 application 和 AndroidManifest 都不一样,以此来区分是独立的 APK 还是 lib,实现方式如下在build.grade里面配置


if (isModuleRun.toBoolean()) {apply plugin: 'com.android.application'} else {apply plugin: 'com.android.library'}


##单 Module 运行需要配置 sourceSets {main {if (isModuleRun.toBoolean()) {manifest.srcFile 'src/main/debug/AndroidManifest.xml'} else {manifest.srcFile 'src/main/AndroidManifest.xml'java {//全部 Module 一起编译的时候剔除 debug 目录 exclude '/debug/'}}}}


3、资源冲突


业务 Module 和 BaseModule 资源文件名称重复会产生冲突,解决方案在每个 module 都有 app_name,为了不让资源名重名,在每个组件的 build.gradle 中增加 resourcePrefix “xxx_强行检查资源名称前缀。固定每个组件的资源前缀。但是 resourcePrefix 这个值只能限定 xml 里面的资源,并不能限定图片资源。个人认为约定大于配置,团队内协定好规范,可以避免冲突。


4、组件通讯组件通讯框架在 github 上有 star 最多的有 ARouter 和 ActivityArouter,前者是个人项目,后者是阿里巴巴开源,权衡之下选择阿里的 ARouter,各业务 Module 之前不需要任何依赖可以通过路由跳转,完美解决业务之间耦合使用方式如下。


if (BuildConfig.DEBUG) { // 这两行必须写在 init 之前,否则这些配置在 init 过程中将无效 ARouter.openLog(); // 打印日志 ARouter.openDebug(); // 开启调试模式(如果在 InstantRun 模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)}ARouter.init(this); // 尽可能早,推荐在 Application 中初始化


compile "com.alibaba:arouter-api:$rootProject.aRouter"每个业务 Module 都需要添加注解 annotationProcessor 'com.alibaba:arouter-compiler:1.1.3'


跳转方法在目标 Activity 上添加 path


@Route(path = ARouterManager.BModuleActivity)public class BModuleActivity extends BaseActivity {@Autowiredpublic String name;@Autowired(name = "age")int age;TextView txt;


@Overrideprotected int getLayoutId() {return R.layout.b_module_layout;}


@Overrideprotected void initView() {txt = findViewById(R.id.txt);

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android笔记:Android-组件化方案探索与思考