Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师

这篇具有很好参考价值的文章主要介绍了Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

美团外卖团队开发的一款Android路由框架,基于组件化的设计思路。主要提供路由、ServiceLoader两大功能。之前美团技术博客也发表过一篇WMRouter的介绍:《WMRouter:美团外卖Android开源路由框架》。WMRouter提供了实现组件化的两大基础设施框架:路由和组件间接口调用。支持和文档也很充分,可以考虑作为我们团队实现组件化的基础设施。

组件化方案

组件化基础框架

在前期的调研工作中,我们发现外卖团队的WMRouter是一个不错的选择。首先,WMRouter提供了路由+ServiceLoader两大组件间通信功能,其次,WMRouter架构清晰,扩展性比较好,并且文档和支持也比较完备。所以我们决定了使用WMRouter作为组件化基础设施框架之一。然而,直接使用WMRouter有两个问题:

  1. 我们的项目已经在使用一个路由框架,如果使用WMRouter,需要把之前使用的路由框架改成WMRouter路由框架。
  2. WMRouter没有消息总线框架,我们调研的其他项目也没有适合我们项目的消息总线框架,因此我们需要开发一个能够满足我们需求的消息总线框架,这部分会在后面详细描述。

组件化分层结构

在参考了不同的组件化方案之后,我们采用了如下分层结构:

  1. App壳工程:负责管理各个业务组件和打包APK,没有具体的业务功能。
  2. 业务组件层:根据不同的业务构成独立的业务组件,其中每个业务组件包含一个Export Module和Implement Module。
  3. 功能组件层:对上层提供基础功能服务,如登录服务、打印服务、日志服务等。
  4. 组件基础设施:包括WMRouter,提供页面路由服务和ServiceLoader接口调用服务,以及后面会介绍的组件消息总线框架:modular-event。

整体架构如下图所示:

分层结构

Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

业务组件拆分

我们调研其他组件化方案的时候,发现很多组件方案都是把一个业务模块拆分成一个独立的业务组件,也就是拆分成一个独立的Module。而在我们的方案中,每个业务组件都拆分成了一个Export Module和Implement Module,为什么要这样做呢?

1. 避免循环依赖

如果采用一个业务组件一个Module的方式,如果Module A需要调用Module B提供的接口,那么Module A就需要依赖Module。同时,如果Module B需要调用Module A的接口,那么Module B就需要依赖Module A。此时就会形成一个循环依赖,这是不允许的。

Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

也许有些读者会说,这个好解决:可以把Module A和Module B要依赖的接口放到另一个Module中去,然后让Module A和Module B都去依赖这个Module就可以了。这确实是一个解决办法,并且有些项目组在使用这种把接口下沉的方法。

但是我们希望一个组件的接口,是由这个组件自己提供,而不是放在一个更加下沉的接口里面,所以我们采用了把每个业务组件都拆分成了一个Export Module和Implement Module。这样的话,如果Module A需要调用Module B提供的接口,同时Module B需要调用Module A的接口,只需要Module A依赖Module B Export,Module B依赖Module A Export就可以了。

组件结构

Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

2. 业务组件完全平等

在使用单Module方案的组件化方案中,这些业务组件其实不是完全平等,有些被依赖的组件在层级上要更下沉一些。但是采用Export Module+Implement Module的方案,所有业务组件在层级上完全平等。

3. 功能划分更加清晰

每个业务组件都划分成了Export Module+Implement Module的模式,这个时候每个Module的功能划分也更加清晰。Export Module主要定义组件需要对外暴露的部分,主要包含:

  • 对外暴露的接口,这些接口用WMRouter的ServiceLoader进行调用。
  • 对外暴露的事件,这些事件利用消息总线框架modular-event进行订阅和分发。
  • 组件的Router Path,组件化之前的工程虽然也使用了Router框架,但是所有Router Path都是定义在了一个下沉Module的公有Class中。这样导致的问题是,无论哪个模块添加/删除页面,或是修改路由,都需要去修改这个公有的Class。设想如果组件化拆分之后,某个组件新增了页面,还要去一个外部的Java文件中新增路由,这显然难以接受,也不符合组件化内聚的目标。因此,我们把每个组件的Router Path放在组件的Export Module中,既可以暴露给其他组件,也可以做到每个组件管理自己的Router Path,不会出现所有组件去修改一个Java文件的窘境。

Implement Module是组件实现的部分,主要包含:

  • 页面相关的Activity、Fragment,并且用WMRouter的注解定义路由。
  • Export Module中对外暴露的接口的实现。
  • 其他的业务逻辑。

组件功能划分

Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

组件功能划分

组件化消息总线框架modular-event

前文提到的实现组件化基础设施框架中,我们用外卖团队的WMRouter实现页面路由和组件间接口调用,但是却没有消息总线的基础框架,因此,我们自己开发了一个组件化消息总线框架modular-event。

为什么需要消息总线框架

既然已经有了ServiceLoader这种组件间接口调用的框架,为什么还需要消息总线这种方式呢?主要有两个理由。

1. 更进一步的解耦

基于接口调用的ServiceLoader框架的确实现了解耦,但是消息总线能够实现更彻底的解耦。接口调用的方式调用方需要依赖这个接口并且知道哪个组件实现了这个接口。消息总线方式发送者只需要发送一个消息,根本不用关心是否有人订阅这个消息,这样发送者根本不需要了解其他组件的情况,和其他组件的耦合也就越少。

2. 多对多的通信

基于接口的方式只能进行一对一的调用,基于消息总线的方式能够提供多对多的通信。

消息总线的优点和缺点

总的来说,消息总线最大的优点就是解耦,因此很适合组件化这种需要对组件间进行彻底解耦的场景。然而,消息总线被很多人诟病的重要原因,也确实是因为消息总线容易被滥用。消息总线容易被滥用一般体现在几个场景:

1. 消息难以溯源

有时候我们在阅读代码的过程中,找到一个订阅消息的地方,想要看看是谁发送了这个消息,这个时候往往只能通过查找消息的方式去“溯源”。导致我们在阅读代码,梳理逻辑的过程不太连贯,有种被割裂的感觉。

2. 消息发送比较随意,没有强制的约束

消息总线在发送消息的时候一般没有强制的约束。无论是EventBus、RxBus或是LiveDataBus,在发送消息的时候既没有对消息进行检查,也没有对发送调用进行约束。这种不规范性在特定的时刻,甚至会带来灾难性的后果。比如订阅方订阅了一个名为login_success的消息,编写发送消息的是一个比较随意的程序员,没有把这个消息定义成全局变量,而是定义了一个临时变量String发送这个消息。不幸的是,他把消息名称login_success拼写成了login_seccess。这样的话,订阅方永远接收不到登录成功的消息,而且这个错误也很难被发现。

组件化消息总线的设计目标

1. 消息由组件自己定义

以前我们在使用消息总线时,喜欢把所有的消息都定义到一个公共的Java文件里面。但是组件化如果也采用这种方案的话,一旦某个组件的消息发生变动,都会去修改这个Java文件。所以我们希望由组件自己来定义和维护消息定义文件。

2. 区分不同组件定义的同名消息

如果消息由组件定义和维护,那么有可能不同组件定义了重名的消息,消息总线框架需要能够区分这种消息。

3. 解决前文提到的消息总线的缺点

解决消息总线消息难以溯源和消息发送没有约束的问题。

基于LiveData的消息总线

组件化消息总线框架modular-event基于LiveData构建,使用LiveData构建消息总线有很多优点:

  1. 使用LiveData构建消息总线具有生命周期感知能力,使用者不需要调用反注册,相比EventBus和RxBus使用更为方便,并且没有内存泄漏风险。
  2. 使用普通消息总线,如果回调的时候Activity处于Stop状态,这个时候进行弹Dialog一类的操作就会引起崩溃。使用LiveData构建消息总线完全没有这个风险。

组件消息总线modular-event的实现

解决不同组件定义了重名消息的问题

其实这个问题还是比较好解决的,实现的方式就是采用两级HashMap的方式解决。第一级HashMap的构建以ModuleName作为Key,第二级HashMap作为Value;第二级HashMap以消息名称EventName作为Key,LiveData作为Value。查找的时候先用组件名称ModuleName在第一级HashMap中查找,如果找到则用消息名EventName在第二级HashName中查找。整个结构如下图所示:

消息总线结构

Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

对消息总线的约束

我们希望消息总线框架有以下约束:

  1. 只能订阅和发送在组件中预定义的消息。换句话说,使用者不能发送和订阅临时消息。
  2. 消息的类型需要在定义的时候指定。
  3. 定义消息的时候需要指定属于哪个组件。

如何实现这些约束

  1. 在消息定义文件上使用注解,定义消息的类型和消息所属Module。
  2. 定义注解处理器,在编译期间收集消息的相关信息。
  3. 在编译器根据消息的信息生成调用时需要的interface,用接口约束消息发送和订阅。
  4. 运行时构建基于两级HashMap的LiveData存储结构。
  5. 运行时采用interface+动态代理的方式实现真正的消息订阅和发送。

整个流程如下图所示:

Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

消息总线modular-event的结构

  • modular-event-base:定义Anotation及其他基本类型
  • modular-event-core:modular-event核心实现
  • modular-event-compiler:注解处理器
  • modular-event-plugin:Gradle Plugin
Anotation
  • @ModuleEvents:消息定义

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface ModuleEvents {
String module() default “”;
}

  • @EventType:消息类型

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface EventType {
Class value();
}

消息定义

通过@ModuleEvents注解一个定义消息的Java类,如果@ModuleEvents指定了属性module,那么这个module的值就是这个消息所属的Module,如果没有指定属性module,则会把定义消息的Java类所在的包的包名作为消息所属的Module。

在这个消息定义java类中定义的消息都是public static final String类型。可以通过@EventType指定消息的类型,@EventType支持java原生类型或自定义类型,如果没有用@EventType指定消息类型,那么消息的类型默认为Object,下面是一个消息定义的示例:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师,2024年程序员学习,android

程,基本涵盖了95%以上Android开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-MoG1yImc-1711634944690)]文章来源地址https://www.toymoban.com/news/detail-855338.html

到了这里,关于Android组件化方案及组件消息总线modular-event实战,渣本Android开发小伙如何一步步成为架构师的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • iOS 组件化的三种方案

    本文主要介绍iOS组件化的三种方案 URL Scheme Target - Action Protocol - Class 匹配 1.1、 URL Scheme路由 使 URL 处理本地的跳转 通过中间层进⾏注册 调⽤ (load方法里把被调用者注册到中间层) 注册表⽆需使用反射 非懒加载 / 注册表的维护 / 参数 URL Scheme路由示例  参考了系统URL Schem

    2024年02月12日
    浏览(28)
  • 【Android】从零搭建组件化项目

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

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

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

    2024年04月27日
    浏览(42)
  • 数据仓库解决方案——ODPS组件化改造之路

    场景还原 不知道你是否在写离线代码时遇到过以下几种情况: 相同的业务代码逻辑分散在各个地方,需要维护多份相似功能代码; 存在多张相同结构的表输入,需要经过相同或相似的逻辑计算加工,并输出给下游表; 有一个计算逻辑非常复杂,需要经过多个子流程或多个节

    2024年04月28日
    浏览(48)
  • 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学习之路(22) 从模块化到组件化

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

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

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

    2024年01月22日
    浏览(69)
  • MVPArms官方快速组件化方案开源,来自5K star的信赖(1)

    基础库(网络请求、图片加载等)的封装 路由框架(页面跳转, 服务提供) 业务组件的划分和代码隔离 0.2.1 业务组件的划分和代码隔离 先说第三点 业务组件的划分和代码隔离 , 现在大部分的文章都围绕着这点, 我这里发表下个人的观点, 第三点确实是很重要的一点, 不管是大厂的

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

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

    2024年02月11日
    浏览(47)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包