【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

滴滴开源 DRouter:一款高效的 Android 路由框架

  • 2021-06-04
  • 本文字数:3493 字

    阅读完需:约 11 分钟

滴滴开源DRouter:一款高效的Android路由框架

DRouter 简介


随着业务不断的发展,业务变的种类繁多,项目代码集中且耦合在一起,导致编译速度慢、开发效率低、维护困难、牵一发动全身。这时无论是从工程效能还是业务迭代稳定性的角度考虑,都需要把项目代码拆分成独立的组件。当组件拆分后,在没有代码耦合的前提下,如何快速、方便、灵活的进行组件间跳转、数据通信、生命周期控制是 DRouter 要解决的问题。


DRouter 支持的功能


  • 使用 URI 字符串导航 Activity、Fragment、View、RouterHandler,支持正则表达式

  • 回调式 onActivityResult

  • RouterHandler、Activity 支持等待异步完成(hold),并可设置超时时间

  • RouterHandler 指定执行线程

  • 注入拦截器,支持全局拦截器和局部拦截器,面向切面编程

  • 更为多样化的 Fragment 页面跳转能力

  • 使用接口或基类导航到实现类 Service 的 Class 以及实例

  • 支持 Service 别名以及多维过滤器查找

  • 导航 Service 可指定任意构造器、支持单例

  • 支持动态注册 RouterHandler、Service,绑定生命周期自动解绑

  • 简单易用的跨进程执行 RouterHandler、Service

  • 跨进程访问无需提前绑定、如同本地调用一样进行访问

  • 支持客户端进程和服务端进程自动重连

  • 支持 VirtualApk


为什么要开发 DRouter  


滴滴乘客端包容万象,拥有众多的业务和组件,早在 15 年就已经启动组件化重构。使用滴滴自研的基于 JavaSPI 插件技术,动态的生成从接口到实现的映射关系,完成了组件化的通信功能,并且应用到了整个滴滴的 Android 体系中。虽然 SPI 性能优良、使用便捷,但同时功能单一、支持的场景少也是一直存在的问题。随着组件化实践的常态化,急需要一款功能强大,适合滴滴的场景,定制化程度高的路由框架。

 

目前市面上已经存在几款路由框架了,比如 ARouter,WMRouter。不过滴滴业务繁多,平台化遍布各种场景,对路由的定制化需求强烈,很多功能市面上的路由是不支持的,比如:

 

  • ARouter 作为路由的先行者,由于开发较早,功能简单、同时路由查找过程性能损耗较大

  • WMRouter 在路由的性能上仍然有一定优化空间,同时没有导航到 Fragment/View、回调式 ActivityResult,使用 ServiceLoader 稍显繁琐且无法动态注册以及多维过滤

  • 现今没有一款路由框架对完整的跨进程和跨应用有较好的支持,这在滴滴定制车团队有着强诉求

  • 同时没有一款路由对 Fragment 提供更多的扩展能力,DRouter 在鸿鹄和车载屏项目以及更多 Fragment 的场景可以提供支持

 

基于以上问题,从 18 年开始自研了 DRouer 路由框架,为滴滴的平台化服务几十种场景。


DRouter 有哪些亮点


▍1 插件增量编译、多线程扫描,运行时异步加载路由表


路由表在编译期通过插件动态生成。插件会启动多线程同时异步处理所有的组件;增量扫描功能可以帮助开发者在第二次编译时,只对修改过的代码进行处理,极大地缩短路由表生成的时间。

 

在本人的开发机上测试,19 年滴滴乘客端扫描 5.5 万个类,全量需要不到 6s 的时间;如果是修改了 application 模块,增量扫描只需要处理修改的单类,耗时 0.4s 时间;如果是修改了 library 组件,增量扫描需要扫描整个 jar 包,根据 jar 包的大小时间会稍多一些,例如滴滴专快组件增量耗时 3.9s。

 

另外框架初始化的时候启动子线程去加载路由表,不阻塞主线程的执行,尽其所能提高效率。


▍2 完整的 Router 功能


支持使用 URI 字符串导航 Activity、Fragment、View、RouterHandler,支持正则表达式、回调式 onActivityResult、拦截器;

 

RouterHandler 还支持异步完成(不阻塞)、指定执行线程等等;

 

同时针对 Fragment,支持单 Page、栈 Page、ViewPager 三种形式的 Fragment 加载。


▍3 强大的 ServiceLoader 能力


DRouter 同样是基于 SPI 的理念,路由表会生成接口或基类对实现类的映射。

 

  • 获取实例时可以指定执行任意构造器、单例、优先级排序、自动拆解所有接口和基类作为 key

  • 可以通过 alias,以及任意数量多的维度对目标进行多维过滤

  • 动态注册


▍4 像调用本地方法一样跨进程通信和回调


无需编写繁琐的 aidl 文件实现跨进程调用,使用方式几乎等同本地导航 RouterHandler 和 Service,只需增加一些配置即可。

 

  • 不需要异步去 bindService 等待,同步执行

  • 支持跨应用

  • 替代反射,服务端使用本地方法执行,提高执行效率

  • 支持任意类型的对象跨进程传递,包括 Context、自定义类,支持 RemoteCallback 回调

  • 服务端异常崩溃重启后,客户端按需自动重新执行已发送的跨进程命令。


▍5 框架内部尽可能减少使用反射,提升性能


加载路由表、实例化路由元素、以及跨进程命令到达服务端后的分发这些常规应该使用反射的场景,使用预占位或动态生成代码来替换成 java 的 new 创建和显式方式执行,最大限度的去避免反射执行,提高性能。

 

考虑到功能的全面性,使用 ServiceLoader 时如指定非默认构造函数以及跨进程时传递自定义类,在框架内部会使用到反射,不过可以使用默认构造函数以及对跨进程对象实现 Parcelable 来避免。


▍6 动态下载与 api 匹配的 plugin,自升级


很多项目包括 DRouter 需要搭配 gradle 插件和 java 依赖来使用,正常来讲升级 java 依赖时大概率需要同时升级 gradle 插件,这在滴滴这种业务线繁多,各业务线除了有自己的组件同时又有自己的壳工程场景是一个非常痛的点。当业务线的组件因平台的同学在公共层升级了 java 依赖后,但又没有同时手动更新自己业务壳工程的 gradle 插件,大概率就会编译失败。

 

DRouter 利用 plugin-proxy 壳插件来解决这个问题,壳插件会在编译期自动检查 java 依赖的版本,同时获得应该匹配的插件版本。接着 plugin-proxy 会去下载这个匹配的 gradle 插件,并最终执行。这样就解决了因升级 java 依赖而 gradle 插件不匹配导致的编译问题。


▍7 无需手动添加混淆规则


DRouter 把混淆规则隐藏到了 java 依赖里,当启用混淆功能时会自动应用混淆规则。这样即使升级了 DRouter 版本也无需关心混淆规则是否需要升级。


DRouter 的原理和架构



整体架构分三层,自下而上是数据流层、组件层、开放接口层。


4.1 数据流层


数据流层是 DRouter 最重要的核心模块,这里承载着插件生成的路由表、路由元素、动态注册、以及跨进程功能相关的序列化数据流。所有的路由流转都会从这里取得对应的数据,进而流向正确的目标。


4.2 组件层


这一层是功能组件层,核心的路由分发、拦截器、生命周期、异步暂存和监控、ServiceLoader、多维过滤、Fragment 路由,以及跨进程命令打包等。


4.3 开放接口层


DRouter 在接口层做了大量的精简和优化,在灵活性和易用性方面做了很多权衡,主要目的是减少冗余 API,使框架更为简单的使用和接入。比如 Request 和 ServiceLoader 作为最核心的 API 方法数非常少,一些不常用的功能会放到 Extend 中。


▍RouterFlow



路由数据流从创建 Request 开始,通过 URI 在路由表中找出所有的结点,会按照 RouterHandler、UI 的顺序以及优先级顺序执行。每一个元素都可以定义自己的拦截器,这里的拦截器必须放行以后才能执行对应的结点;同时对于 RouterHandler 执行完又可以决定是否拦截后面所有的结点。当所有的结点执行完,且异步暂存态也都已释放,最终把结果回传给请求处。


▍ServiceFlow



ServiceLoader 既可以获取 Class 也可以获取对象实例,核心是路由表和过滤器,其中 FeatureMatcher 拥有多维过滤的功能。像滴滴这种多业务场景的应用,在使用 MVP 架构时对 P 的匹配至少会需要根据所在国家、订单业务线、订单状态三个维度来分别对应唯一的 Presenter,多维过滤就很容易解决这个问题。性能方面,对象实例化会根据构造器类型,利用插件生成的 RouterProxy 代码通过 new 来实例化无参对象(默认构造)或者反射实例化有参对象(非默认构造)。


▍RemoteFlow



DRouter 的跨进程功能是一大特色,左侧绿色代表客户端,自上而下会把所有的参数打包成命令,这里支持任意类型,框架内有一套完整的机制通过遍历集合、转换、组装,最后存储到 Parcel 里。利用 Authority 查找到服务端的 Provider 并随之利用此通道返回服务端的 Binder。


在服务端,也就是右侧的紫色,会自下而上把命令解包和分发。然后利用 DRouter 的路由 RouterHandler 和 ServiceLoader 的功能,使得客户端的命令最终在服务端执行。插件会在服务端生成一段代码,这段代码可以避免使用反射,提高整体的执行效率。

 

整个过程同步执行,使用简单、高效。


写在最后


DRouter 是一套功能完善、定制化程度高的路由框架,具有易于上手、架构清晰、性能优良的特点。现已成为滴滴不可或缺的基础组件之一。DRouter 作为组件化方案的践行者,将继续提升各个场景的支持能力,也欢迎各位开发者使用并提出宝贵的反馈意见。

 

GitHub 开源地址:https://github.com/didi/DRouter



头图:Unsplash

作者:DRouter

原文:https://mp.weixin.qq.com/s/c6E7NOKNWbTNYDLZRWAwSw

原文:滴滴开源 DRouter:一款高效的 Android 路由框架

来源:滴滴技术 - 微信公众号 [ID:didi_tech]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-06-04 08:002541

评论

发布
暂无评论
发现更多内容

小程序容器技术,App热更新与敏捷开发新方案

Speedoooo

敏捷开发 APP开发 热更新 小程序容器 动态更新

Git 如何回退代码

秋天

一文搞定 Flutter 底部弹窗实现

岛上码农

flutter 跨平台 ios开发 Android开发 3月月更

数字化原住民|ONES 人物

万事ONES

软件 招聘 软件工程师

《软件开发的201个原则》思考:4. 高质量软件是可以实现的

非晓为骁

个人成长 软件工程 软件开发

在线HTML压缩格式化工具

入门小站

工具

收藏很久的资源整合网站,一个网站一个世界

小炮

多场景推进 服务网格在联通的落地实践(下)

百度大脑

Python迎来31岁生日,蝉联年度编程语言排行榜冠军

Python猫

Python

Redis集群架构剖析(3):集群处理redis-cli指令

非晓为骁

redis 架构 分布式 redis cluster

什么技术,让浩鲸科技拿下中国移动大奖?

鲸品堂

中国移动

Centos7安装Nginx

云原生

nginx centos 部署

春分耕种时,AI“现身”田间地头

百度大脑

使用 ABAP 开发的一个基于 Web Socket 的小工具,能提高程序员日常工作效率

Jerry Wang

自动化 前端开发 websocket 程序员进阶 3月月更

TDesign 更新周报(2022年3月第3周)

TDesign

深入浅出事务的本质,附 OceanBase 事务解析14问!

OceanBase 数据库

oceanbase OceanBase 社区版

电脑就是我的安全感|ONES 人物

万事ONES

招聘 软件工程师

从 SVN 迁移到极狐GitLab

极狐GitLab

svn 迁移 极狐GitLab

计算机编码规则之:Base64编码

程序那些事

Java base64 nio 程序那些事 3月月更

如何在新公司快速落地

Hockor

centos7.6安装MySQL5.7采坑指南

云原生

MySQL 数据库 sql centos

母婴后浪品牌频出,各个细分市场有哪些发展潜力?

易观分析

母婴

敏捷实践|好的用户故事怎么写?

LigaAI

用户故事 敏捷实践

“StarRocks 极客营” 重磅来袭,和技术大牛一起推开数据库梦想之门!

StarRocks

数据库 大数据 StarRocks

小程序电商微服务设计

唐尤华

架构实战营

恒源云(GpuShare)_MaskFormer:语义分割可以不全是像素级分类

恒源云

语义分割 像素分割 MaskFormer

网络安全:绕过MSF的一次渗透测试

网络安全学海

黑客 网络安全 信息安全 渗透测试 安全漏洞

科幻变现实:喷下即疗愈,生物3D打印绘就生命密码图

脑极体

一周热点回顾|虎符交易所上线多链合一;俄央行称加强监控加密资产等P2P交易

区块链前沿News

区块链 虎符交易所

743 网络延迟时间

好吃不贵

Kubernetes API规范:为optional的字段使用pointer

工程师薛昭君

API Kubernetes 集群

滴滴开源DRouter:一款高效的Android路由框架_文化 & 方法_滴滴技术_InfoQ精选文章