

安卓组件化之框架设计
source link: https://blog.bihe0832.com/android-dev-architecture.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

这篇文章主要总结和介绍开发框架的设计。框架核心就是组件化开发,设计中遵循组件单一职责、分层、高内聚低耦合、依赖倒置的原则。
框架设计的背景
在终端项目的开发中,我们都绕不开几个问题:
-
应用内的业务关系复杂,耦合程度高,开发维护复杂
很多业务甚至单个项目只有一个模块,然后各业务功能相互依赖和调用。一些核心业务动辄就是上万行的代码,关键是里面一半以上的代码是和自身逻辑没有直接关系的。
当然UI也是如此,多个功能整合在一个界面里面,界面的数据、UI、操作等没有分离,有些首页一个UI文件基本上就包含了整个应用的大部分界面。然后因为再通过各种业务逻辑互相耦合的去控制UI表现。
如果前期没有做好解耦,当随着业务增加,项目成员越来越多的时候,项目开发维护的成本会非常高。这样复杂的关系下无论是新功能开发还是老版本调整都会非常痛苦,甚至下线个已有的功能都非常复杂,引入一堆问题。
-
项目随着发展越来越大,开发效率越来越低
当项目发展到一定阶段,逐渐庞大以后,由于需要编译的内容太多开发过程中编译、构建等都会耗费大量的开发时间。即使可以使用instant run等工具优化编译的时间,但都是治标不治本,开发的效率并不会很明显
-
虽然不同项目间可以复用的代码很多,但是平时开发中都习惯了只有一些完备的功能才使用或者找专门的类库。
对于一些简单又常用的基础和公共逻辑,目前代码复用的方式:
-
还停留在代码文件或者代码片段的复用,而且可能每次都是用的时候随便网上找,搜索复制粘贴
-
有些时候为了赶需求,项目中已经有一份了,但懒得找,再引入一份进来。
-
这些代码明明是基础逻辑,但是却和业务逻辑存在大量耦合
这种代码复用的方式会带来的最大问题就是对于同一个逻辑怎么同步修改所有使用的地方。这种修改可能是你做的一些定制化的修改,也可能是本身的bug修复。由于是复制粘贴,所以你可能也不记得还有哪里用过。结果就是同一个问题反复遇到,反复修改。而且随着时间积累,这些代码的差异越来越大,开发维护的成本就会越来越高
这样的代码复用还有一个很常见的现象:对于一个项目研究的成熟方案想迁移到另一个项目结果发现只是需要一个小功能,结果迁移过去了原项目的大部分代码。
-
框架设计方向
在终端开发的框架发展演进的过程中,也一直通过各种方法来优化解决上面的问题。
-
通过模块化来降低业务代码和基础框架以及业务逻辑之间的代码耦合
-
通过组件化将公共逻辑、基础功能按照单一职责进一步解耦,抽离为组件,组件和业务分别独立维护,减小业务规模。
目前主流的开发框架一般都是三层(基础库、业务公共逻辑、业务模块),然后所有模块单向依赖,例如下图。
这种框架设计结构简单明了,而且单向依赖模块之间的耦合就可以大大减小,但是他存在一个缺点,随着业务的增长,模块越来越多,还是会越来越膨胀。
我们的框架设计和主流方案一致,几个设计的核心原则是单一职责、分层、高内聚低耦合、依赖倒置。所有的UI内容都是基Fragment进行开发。
通过将业务分层并拆分为组件来降低业务与基础能力和公共能力的耦合。同时利用远程maven库、本地lib等结合自动构建,将已经开发完成的组件二进制化。开发中仅仅引入功能相关的源码,其余组件通过二进制依赖引入,日常通过各种宿主壳以更小的单元开发,提升开发效率。
我们的框架设计共有四层。
基础组件层,主要是自己沉淀或者统一对比以后选择的第三方技术栈,与业务无关,可通用。
框架组件层主要是两个,Framework 和 Application ,他们负责通用资源、公共声明、页面路由以及对于底层第三方库的二次封装。Framework 也与业务无关,可通用;Application 与业务相关,包含一些公共资源定义等。
业务组件层是具体的一个业务特性的业务逻辑,例如页面卡片、广告等。
应用组件是可以独立运行的最小单元,而且他们基本只是一个Android Application 的空壳加一些配置文件,所有的业务逻辑都在业务组件层实现。其中里面比较特别的是APPTest,他既是底层业务组件开发中的临时入口,同时也是一些基础功能 和 所有 Pub的测试入口(可以参考:安卓组件化之组件调试和运行 )。
为了后续的规划,目前对于功能模块拆分基本上还是按照单一职责、分层、高内聚低耦合。通俗点的就是下面的几个原则
-
模块拆分尽可能原子化,一个模块聚焦一个功能
-
同一功能对外接口暴露尽可能少
-
同一功能覆盖尽可能多的场景,且兼容性尽可能好
在开发中,我们经常会发现,会因为业务需求的原因,两个原本相对独立的两个模块产生了耦合。这种耦合一般是两种:
-
页面通信,我们和第三方跳转等外部通信统一,均通过 router 实现解耦。使用路由还有一个好处就是可以方便的处理各种通用拦截,例如检查登录态,弹出广告,检查权限等。这部分内容 安卓组件化之组件通信及拦截 有单独介绍
-
对于数据耦合,我们通过使用 livedata 将业务的数据展现与数据操作分拆到不同的组件,然后已有的两个组件共通依赖数据组件来进一步解耦。没有什么是多分一层解决不了的,有就分两层。
在组件化开发中,对于不同层级的组件,通过自动构建,我们会生成不同的构建产物,供其他层级的组件使用:
-
基础组件层通过自动构建,会被提交到私有Maven库里面,后续远程引入。
-
框架组件层前期源码依赖,后期通过自动构建,提交到本地的依赖库,通过AAR引入。
-
业务组件层开发结束以后通过自动构建,提交到本地的依赖库,通过AAR引入。
-
应用组件自动构建会生成对应模块的APK文件
对于上面的四层组件之间的依赖关系主要遵循下面的几个原则:
-
整体遵循依赖倒置原则,所有依赖只能单向,只能依赖同级或者下级的组件,绝对不可以反向依赖。
-
对于下级组件的依赖,没有限制,随意依赖。
-
业务组件与应用组件,不直接依赖基础组件,基础组件统一有框架组件管理。
然后再具体开发中,对于一个组件什么时候通过源码依赖,什么时候二进制依赖,可以查看文章 安卓组件化之组件管理(导入、依赖、升级)。
Recommend
-
128
阅读文本大概需要 6.6 分钟。
-
101
微服务化之无状态化与容器化
-
75
微服务实战(五):微服务化之缓存的设计
-
102
问题 在组件化的时候我发现遇到这些问题 组件可以访问其他组件所有Public的类,代码不内聚 组件依赖传递导致API向下不兼容会崩溃 API方法手动写在MarkDown 模块之间互相依赖会照成循环依赖无法编译 需要人工写接口库、实现库我写了一个Gradle插件ModuleExport解决...
-
56
本文章为《互联网高并发微服务化架构实践》系列课程的第五篇 前四篇为:
-
69
随着公司业务的不断发展,应用的代码体积将会越来越大,业务代码耦合也越来越多,代码量也是急剧增加 如果仅仅完成代码拆分还不足以解决业务之间的代码耦合,而组件化是一种能够解决代码耦合、业务工程能够独立运行的技...
-
32
这篇文章总结组件化开发框架怎么通过自动构建,完成一套代码同时支撑超过5款以上的APP的构建发布等。 写在前面 在平时日常的版本发布中,由于很多版本相关的字段是通过手动维护的,我们经常会遇到下面的问题: ...
-
34
这篇文章主要总结了我们基于路由的组件通信怎么设计的,以及怎么基于路由处理通用拦截及页面返回等逻辑。 路由能力介绍 在考察了多个路由组件以后,结合我们的场景需求,基于 ActivityRouter
-
11
安卓组件化之组件调试和运行 「 终端开发 」 —— 2020年08月22日 [本文结构] 这篇文章总结组件化开发框架怎么基于组件化更好的提升开发效率。...
-
8
安卓组件化之组件管理(导入、依赖、升级) 「 终端开发 」 —— 2020年08月21日 [本文结构] 这篇文章主要总结组件化开发框架中,我们是怎么通...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK