感谢苍王的组件化架构,借鉴了很多。
很多内容会慢慢细化总结。
简介
为什么组件化
其实不是为什么,而是发展的必然趋势。
先看下正常模块化。
模块化1.PNG当我们页面越来越多,业务模块耦合越来越严重,代码非常难以维护,更难测试,扩展性非常差。 一旦一个模块入口变更,很多模块需要修改,关联业务都需要测试,两个不同的APP很难公用模块。 打个比方京东商城和京东金融,支付模块和登录模块从页面角度来讲无法公用,其实业务逻辑上来讲公用性很强。所以组件化就此诞生。
模块化:多module划分业务和基础功能
模块:是独立的业务模块,如直播模块(LiveModule)、首页模块(HomeModule)、即时通讯模块(IMModule)等。
组件:单一的功能组件,如:视频组件(VideoSDK)、支付组件(PaySDK)、路由组件(Router)等,每个组件都能单独抽出来制作成SDK。
模块化和组件化的区别:模块化是业务导向,组件化是功能导向。
组件化和模块化缺点:旧项目重新适配组件化的开发需要相应的人力和时间成本。
模块化开发好处:
-
业务模块解耦,业务移植更加简单。
-
多团队根据业务内容并行开发和测试
-
单个业务可以单独编译打包,加快编译速度
-
多个APP共用模块,降低研发和维护成本
组件化开发好处:
-
避免重复造轮子,合理的安排人力,降低研发和维护成本
-
不同项目共用一个组件或模块,确保整体技术方案的统一性
-
为插件化共用同一套底层模型做准备。 终极目标插件化。
组件化的基础
AndroidStudio的依赖是组件化的基础
-
既可以依赖jar也可以是.arr(可以包含android特有资源)
-
module依赖
-
同一层级:表示
-
自身目录fileTree
-
-
本地库和网络库
后续会添加单独的Gradle连接
分层
分层来源于多人合作开发。模块相互独立,独立开发,最终合成。
模块化分层
-
基础层(BaseModule) 集成了工具和封装框架,例如数据库、图片等,均为轻量级封装
-
业务层 每个模块相互独立,因为页面逻辑简洁,单独的页面可以划分为单一的功能模块,只需一个BaseModule就可以完成基础工具库的依赖
-
应用层AppModule 统筹整个APP的集成层,最终被编译打包成App
组件化分层
这种架构要求组件独立复用,模块能够不依赖其他模块实现。 模块层的业务逻辑需要考虑业务之间的信息交互和转发的实现。
-
基础库层 更加基础的库类依赖,此层 非必须,例如Rxjava、EventBus等一些代码结构优化的库,还有自己编写的封装类。 基础库层可以转移到基础层和组件层中,这样可以减少层级
-
组件层 将图片加载、网络HTTP、Socket等基础功能划分为一层。
-
基础层 基础组件的整合,提供基础组件能力给业务层使用。 基础层可以只是一个空壳,起到隔离模块层和组件层的入口作用;可以作为中转,封装一些必须要使用的组件功能,隐蔽一些实现细节。
-
模块层 每个模块相当于一个业务,通过Module来分隔每个业务的逻辑,一个模块由多个不同的页面逻辑组成。
- 应用层 生成App和加载初始化操作。 componentized-1.png
多模板化
多模板化是融合了组件化分发后演化而来的架构。
在模块化的前提,使用组件化分发,单页面中分发出多个独立的业务。 模板层服务于多个分发业务的组装。 在模板层中,一个模板包含多种业务,一个页面可以使用多个模板的逻辑。 例如,直播间和QQ聊天室,当有多个特别模板的布局组装和位置变更时,就需要配置模板。 多模板化的产品要求样式多变,其衍生架构演变是模块化进化的一个方向 componentized-2.png插件化
当分层已经非常稳定后,热修复、热更新技术催生出了插件化开发。 适合多个业务模块动态迭代。一个小组可以负责一个业务工程,脱了原来宿主工的研发。
-
组件层中需要添加插件框架,如Small、Atlas、RePlugin等,根据项目情况作出选型,选型调研尤为重要。
-
模块层的每个模块是以业务是否独立作为划分条件,例如,地图、直播间、活动、第三方嵌入,做为单独的研发分支(SVN、Git工程)。每个模块作为基础项目研发,模块之间相互独立,项目达到最大程度解耦。
-
应用层对应插件化宿主App,一些非常基础的业务如登录、支付等需要账号的模块基础到这来。
如果公司对这些模块有很好的插件化加载方案和解耦能力,可以选择使用这些分离技术。
宿主App只是一个壳,用于初始化插件化框架,并加载不同的模块。
插件化问题:
-
解决资源冗余,包括对Base Module的依赖和库依赖
-
资源混淆和资源冲突
-
插件加载方式
-
通信依赖、数据交互、事件机制。
举个模块间通信机制的例子,假如用RxBus进行通信,每次都需要添加一个新的类,每个事件类都需要添加到Base module中。通信机制的架构非常不稳定,功能叠加后模块越来越多,会造成类爆炸。需要设计接口向前兼容,就得接口不能进行过多的修改,不能删除和更改参数,只能增加。
componentized-3.png
进程化
当App越来越大时,比如已经达到了支付宝、微信、商城这种超大型级别,一个App占用几百MB以上空间时,几乎需要使用Android开发的全部功能。
为了让系统给App分配更大的内存,更加流畅的运行,就开始进程化。 因为Adnroid系统是以进程为单位限制内存和资源分配不是APP。
进程定义需要以四大组件为入口,四大组件在AndroidManifest.xml中使用process字段来声明额外的进程。
分层说明:
- 进程层是以非常大的功能业务为划分条件,例如:播放视频、拍照、播放音乐、地图导航、游览web等非常消耗内存的模块。
好处:
-
使APP获得更多内存,运行更加流畅,避免单进程内存过大而不断回收内存导致的卡顿问题,避免内存过低被系统杀死。(一些播放视频、播放音乐、拍摄、游览网页等非常耗费资源的操作放在其他进程)
-
有效避免OOM问题,单进程崩溃不影响应用的使用(如果滥用内存还是没办法避免)
问题:
-
跨进程的通信和交互比组件化、模块化更加复杂。 多进程通信方式:
通信方式 优点 缺点 Bundle 简单易用 只能传输基础数据类型和实现P 四大组件间通信 文件共享 简单易用 不适用高并发场景,并且无法做到进程间的及时通信 无并发访问的情形,交互简单的数据实时性不高的场景 AIDL 功能强大,支持一对多并发通信,支持实时通信 使用稍微复杂,需要处理好线程同步 一对多通信且有RPC需求 Messenger 功能一般,支持一对多串行通信,支持实时通信 不能很好处理高并发情形,不支持RPC,数据通过Message进行传输,因此只能传输Bundle支持的数据类型 低并发的一对多即时通信,无RPC需求,或者无需要返回结果的RPC需求 socket 功能强大,支持一对多的并发数据共享,可以通过call方法扩展其他操作 可以理解为受约束的AIDL,主要提供数据源的CURD操作 一对多的进程间的数据共享 ContentProvider 功能强大,可以通过网络传输字节流,支持一对多并发实时通信 实现细节稍微有点繁琐,不支持直接的RPC 网络数据交互(Android系统内部也有很多地方用的socket) -
静态成员和单例模式失效。
-
线程同步机制完全失效
-
SharedPreferences的可靠性下降,因为没有对多进程支持。
-
文件读写的时候,需要考虑并发访问文件的问题。
-
SQLite很容易被锁,其他进程访问时就会报出异常。
- Application多次创建。(多次onCreate,只能通过进程名来区分) componentized-4.png
网友评论