1、百链 CC
核心代码量:3K(±) line (&插件)
源码阅读难度(10分制):8(Socket&ASM)
组件自动注册方案: 自动注册
TrasnformAPI + ASM扫描组件类(IComponent接口实现类)并注册到ComponentMananger中,
无需手动维护组件列表
模块间通信机制:
事件总线
组件间跨进程通信机制: Socket
广播 + Service + LocalSocket
组件向外提供服务: 自动注册
在IComponent中实现,自动注册到ComponentMananger
组件依赖隔离:
无需依赖、完全隔离
特点:
1. 可以跨app调用,初期改造时即可单独编译组件运行
2. 提供统一的组件调用及实现方式(不管是否跨app调用、页面跳转、服务调用、同步/异步调用)
3. 组件自动注册,无需维护
4. 提供了ActionProcessor按需加载的支持
综合成本:中
侵入性低
无混淆
改造成本中
学习成本低
维护成本中
缺点:
1、使用Socket实现组件间通信,逻辑略复杂,且只支持string
2、Socket未使用NIO,只能一对一通信
3、组件与非组件状态下通信机制不统一
4、无法自动唤醒目标,目标组件被杀后无法通信
2、得到 DDComponentForAndroid 现更名为JIMU
核心代码量:1.2K(±) line (&插件)
源码阅读难度:5(Javassisit)
组件自动注册方案: 自动注册
apt生成各module的路由表
TrasnformAPI + javassist将IApplicationLike的注册代码生成到自定义application.onCreate方法中,
无需手动维护组件列表
模块间通信机制:
路由 + 接口下沉
组件间跨进程通信机制:
不支持
组件向外提供服务: 手动注册
接口下沉到base中,组件中实现接口并在IApplicationLike中手动注册到Router中
组件依赖隔离:
通过插件实现只在打apk包时才添加依赖,编码期间不能直接调用其它组件的代码
特点:
自动添加依赖,只在运行assemble任务的才会添加依赖,因此在开发期间组件之间是完全感知不到的,这是做到完全隔离的关键
支持两种语法:module或者groupId:artifactId:version(@aar),前者之间引用module工程,后者使用maven中已经发布的aar
1. 编码期间组件依赖通过插件进行隔离,避免直接调用其它组件的代码
2. 提供了兼容ARouter的方案
3. 组件自动注册,无需维护
综合成本:中
侵入性一般
混淆所有下沉接口、框架中相关接口的实现类等
改造成本一般
学习成本一般
维护成本一般
缺点:
1、不支持组件间的跨进程通信,这个期望后续能有进展
2、javassisit经常会占用代码资源无法释放,导致编译失败(mac下不会,wins下经常,无解)
3、组件与组件联合测试时需要集成打包到一起,而不是两个独立的组件通信
3、58赶集 ModularizationArchitecture
核心代码量:2K(±) line
源码阅读难度:7(AIDL)
组件自动注册方案: 手动注册
1. Action列表在其所属的Provider中注册
2. Provider在其所属的ApplicationLogic中注册
3. ApplicationLogic在主app的Application中注册
模块间通信机制:
事件总线
组件间跨进程通信机制: AIDL
组件同时安装在设备上即可,实际开发中一般是当前正在开发的组件和主app中的组件互相调用.
组件向外提供服务: 手动注册
实现一个对应的Action并在其所属的Provider中手动注册
组件依赖隔离:
无需依赖、完全隔离
特点:
1. 可以跨app、app内跨进程调用
2. 组件运行在各自进程中,单独运行与联合打包切换时需要修改进程名称
3. 组件需指定同步实现还是异步实现,调用组件时统一拿到RouterResponse作为返回值,可以自行决定同步还是异步方式调用RouterResponse.getData()来获取结果,但异步获取时需要自己维护线程
综合成本:高
侵入性高
混淆所有下沉接口、框架中相关接口的实现类等
改造成本高
学习成本高
维护成本高
缺点:
1、使用AIDL实现组件间通信,逻辑略复杂
2、组件与非组件状态下通信机制不统一
4、阿里Arouter
组件自动注册方案: 半自动+反射
1. apt生成各module的路由表
2. Arouter初始化时扫描所有dex找出指定包名下的路由表,通过反射进行统一注册
模块间通信机制:
路由 + 接口下沉
组件间跨进程通信机制:
urlScheme来统一转发
组件向外提供服务: 反射
接口继承IProvider并下沉到base中,组件中实现接口并通过注解来暴露服务
组件依赖隔离:
未隔离
特点:
1. 阿里出品,使用者众多,QQ群里交流比较活跃
2. 自动注册插件正式启用之前扫描所有dex完成注册的方式效率较低且有加固厂商兼容性问题
3. 分级按需加载
综合成本:一般
侵入性高
混淆框架中的所有类及框架相关接口的实现类
改造成本一般
学习成本一般
维护成本低
5、美团
组件自动注册方案: SPI+javassit
1. 使用servieloader进行解耦---非显式的调用服务实现类
2. javassit预处理:大体流程是
在build的某个阶段拿到所有编译后的class文件(夹)和jar包。
使用javassit确定哪些类被@autoService修饰,配置文件中如果不存在,在其添加。
查看serviceConfig配置文件里面的格式是不是正确。
通过javassit来确定serviceConfig配置文件里面的类是不是在项目中存在,接口类是不是实现了Iprovider接口。
模块间通信机制:
LocalBroadcast取代eventbus
组件间跨进程通信机制:
contentProvider
组件向外提供服务: 反射
接口继承IProvider并下沉到base中,组件中实现接口并通过注解来暴露服务
组件依赖隔离:
无需依赖、完全隔离
特点:
1. 解耦使用serviceloader,而不是路由进行
2. 可以无侵入式的配置各种服务
3. lib快速便捷多端使用
综合成本:高
侵入性低
混淆框架中的所有类及框架相关接口的实现类
改造成本高
学习成本高
维护成本高
6、其它
聚美Router
APT+反射
51信用卡路由方案OkDeepLink
使用aspectJ来实现路由表的自动注册
美柚路由方案RouterKit
通过apt生成每个module的路由表,然后复制到app的assets目录,
运行的时候遍历asset目录,反射对应的activity
7、思考总结
1、组件自动注册方案:
现有APT实现的Router 只需要完成中央注册即可
可选方案复杂度:10分制
javassisit 7
ASM 8
SPI 0
AspectJ 9
反射 6
2、组件间通信方案:
可选方案复杂度:
ContentProvider 7
Socket 8
AIDL 7
Messenger 3
由于现在的组建内通信方案OkBus 传递的是Message
进程间通信可以使用Messenger(IPC)来扩展OkBus实现组建间的Message的双向传递 几乎0成本
8、最终实现 Moduler
原理篇: https://www.jianshu.com/p/a73fd5e4cad1
核心代码量:1K(±) line
源码阅读难度(10分制):3(Messenger)
组件自动注册方案: 自动注册
APT+SPI
模块间通信机制:
OkBus
组件间跨进程通信机制: Messenger扩展的 OkBus
OkBus
组件向外提供服务: 自动注册
OkBus+SPI
组件依赖隔离:
无需依赖、完全隔离
特点:按需加载,自动唤醒
1、最小代价组件化,最简单的配置、最灵活的切换
2、组件路由自动化注册,中央路由自动化采集
3、服务自动注册,兼容同异步,兼容跨/同进程,经典C/S架 构,一对多通信
4、OkBus实现的通信机制,兼容同异步,兼容跨/同进程,与传统使用方式完全一样,无感知无差别
5、跨组件调用时自动唤醒,单个组件调试时无需手动打开目标组件,即使目标开启后被杀掉进程,同样可以唤醒加通信一步到位
跨进程的优点
考虑到,a,b两个模块同时修改,联合调试时,编译过程比较麻烦,因此,所有的组件化框架都不建议开发阶段使用aar,而建议直接依赖
而跨进程通信则完全没有这个烦恼,两个组件单独安装即可,不存在任何依赖
前者的时间复杂度是2+2 后者的时间复杂度是1+1
开发初期,多个模块联合改动,分别测试时,使用aar时间成本是指数增长,使用跨进程只是简单的线性增长。
真正复杂的流程也不是组件化之后的开发过程,而是组件化过程中拆分的各个组件时联合测试的过程,所以一般组件化的过程都会分为两个阶段,组件化开发期,和组件化稳定期
目前的demo给出的解决方案就是组件化开发期的解决方案,稳定之后,会有后续的aar依赖优化方案
综合成本:低
侵入性低
无混淆
改造成本低
学习成本低
维护成本低