写点什么

滴滴国际化项目 Android 端演进,一个小例子彻底搞懂 Android 的 MVP 模式到底是什么

用户头像
Android架构
关注
发布于: 39 分钟前

(1) 海外地图选型考察点



我们对地图强依赖,有些定制需求,如:很多 Marker 并且添加后需要修改、画圆并可以动态调整半径等等


国外可用地图数据源主要有 OpenStreetMap、Here、Tomtom,OpenStreetMap 是个开源的地图数据源,类似维基百科的模式,所以数据很全很新,甚至超过 Google Map,但不可避免会有些脏数据,前期的话我们主要是针对大城市,OpenStreetMap 的数据可以满足我们的需求。


因为涉及到异地跨时区沟通,所以我们希望技术支持力度够大。


性能包括地图启动时间、渲染速度、前端响应速度、后端响应速度。


在开始国际化前,当时滴滴的安装包就已经很大了,基本是国内主流 App 之首(当然现在滴滴 App 已经挺小了),所以我们希望新的地图够小。


(2) 海外地图全面对比



这次我们调研了 Mapbox、Nutiteq、Here、Tomtom、Bing 共五款海外地图。其中


Bing 没有 Android 版;


Tomtom 有很古老的 Android 版,但功能过于简单,文档又几乎没有;


Here SDK 高达 40M,与他们沟通后,精简也只能到 25M,这个大小对我们是绝对接受不了的;


所以我们重点集成和测试的是 Mapbox 和 Nutiteq 这两家地图供应商。


Mapbox 和 Nutiteq 的功能和性能都满足我们需求,地图数据源也都是以 OSM(OpenStreetMap) 为主。


Mapbox 的 API 设计和国内地图类似,都是向 Google Map 靠拢,所以上手简单,并且整个 SDK 都是开源的,地图的样式也更美观些,而 Nutiteq 的地图底层设计比较独特,API 用法很不寻常,这也给我们接入带来了很大的麻烦。


Mapbox 有众多的 Web 用户,包括访问量都不低的 Foursquare、Pinterest 等,但 Android 端用户并不多;Nutiteq 的 Android 用户多些,但整体量也不是很大,不过我们并没有更好的选择,而且前期我们的量也不会很大,所以他们都在可接受范围内。


综合下来看的话,我们是更倾向于 Mapbox,不过 Mapbox 只能通过 GitHub Issues 和邮件反馈问题,反应很慢;Nutiteq 可以 Skype 沟通,效率很高。为了保险起见,Mapbox 和 Nutiteq 都做了全面接入和测试,最终证明这样是有用的。


跟多数 App 一样,为了使得包更小,我们的主工程配置了 abiFilter “armeabi”,仅打 armabi 的 so,而 Mapbox 的 armeabi so 无法跑在 armv7 机器上,前期集成测试我们通过修改 Gradle 脚本在编译时 copy so 的方式让测试通过,而 Mapbox 一直不愿意改,国内市场又不支持 Google 的 Apk Splits 机制,所以最终放弃 Mapbox 而选择 Nutiteq。


后话:经过过滴滴这次合作事件后,Mapbox 开始重视起国内市场,在国内成立了研发中心,沟通方便了很多,并且最新已经解决了上面 arm so 的问题。

1.2 地图切换

用不了 Google Map 带来一个要求,我们选择的地图必须支持多国家,并且在设计时要支持以后不同地图任意切换。是的,即地图和 App 弱依赖。针对这个问题我们设计了地图隔离层。


总体设计如下:



上图第二层 MapSDK 是地图的标准 API 层,App 只与此层打交道,标准层的 API 设计以 Google Map API 为标准。


第三层 Adapter 层是具体地图到标准 API 的适配实现层。每个地图都有个 Adapter,负责将地图 API 转换成标准 API。


将原来的 App 与三方地图直接依赖改为 App 依赖表示标准 API 的 MapSDK 层,由 MapSDK 通过具体的 Adapter 调用三方 SDK,这样地图切换只需要替换依赖的 Adapter 即可,其他地方无需改动。


新的设计后编译依赖关系如下:



App 依赖 Map Adapter,Map Adapter 依赖我们的 MapSDK 和三方的 Map SDK。


当我们需要更换三方地图 SDK 时,仅需更换对应的 Map Adapter 即可。对于 Android,build.gradle 中更换依赖即可。

1.3 新的地图模块设计的好处

(1) 解耦,切换成本低


这个上面已经介绍,再也不会因为换了地图牵一发而动全身。


(2) 学习成本低


业务开发人员只需要熟悉标准 MapSDK API 即可,不用了解其他地图的具体使用,时间成本降低。


(3) 通用


适用于所有 App,以后新增 App,可直接使用之前成型的 Adapter。

1.4 地图切换实现的注意事项

(1) 所有 API 适配


理论上 MapSDK 应为地图所有 API 最大集,实际可以根据情况先去做所需功能的定义和适配。


(2) 标尺


需要统一标尺,如缩放尺度、相同坐标系等。


(3) 未支持 API 处理


因为标准层的 MapSDK 是地图功能最大集,所以不可避免某些三方地图不支持 MapSDK 定义的功能。比如根据一组点缩放这个功能,其对应的 Adapter 在实现这个功能时如果是 Debug 模式则抛异常,Release 模式则空实现。


还有如 MapSDK 的 API 规范前面已经介绍过以 Google Map API 为标准。另 Adapter 有具体的开发规范要求。

2. 漫游网络

前面介绍过我们初期针对的是国内用户海外打车场景,这时用户是用国内手机和运营商海外漫游接入网络,所以需要针对网络访问进行优化。


一般漫游网络流程如下图:



用户由海外运营商接入国内运营商,再通过公网(有墙)访问 Web。我们的服务器部署在 AWS 上,用户海外漫游打车网络流程如下图:



由于公网访问 AWS 非常慢,我们添加了海外专线,优化后用户海外漫游打车网络流程如下图:



用户先访问到国内的中转服务器,中转服务器再通过海外专线访问 AWS。


这个过程中客户端要做的工作包括: (1) 拉取中转服务器域名列表


(2) 使用中转服务器域名列表中域名访问,出错则用原始域名降级重试


(3) 定时及推送更新域名列表


这里域名顺序由服务端自己负载均衡,返回的中转服务器域名列表是中转服务器域名还是直接海外域名也由服务器决定。

3. Android 项目演进

3.1 原有模式

之前国际化业务的工程是很简单的方式,所有业务、组件、工具放在一起,根据具体包名划分:



这个在早期问题不大,并且开发起来快速方便,但随着更多业务接入,如我们前面说过的新的国家运力接入,问题就日益明显,包括:


(1) 组件之间耦合


虽然已经划分包名,但依然可以互相调用,组件间依赖关系不清,甚至有循环依赖。


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


(2) 添加新业务不便


(3) 开发问题


规模越来越大致提交冲突可能性变大。

3.2 SDK 工程提取

将原工程整体拆分为业务工程和 SDK 工程,单业务工程直接依赖 SDK,可独立开发、独立运行、独立打包。如下:



这样在接入新的业务后,总体项目结构如下图:



每个业务作为单独工程,共用组件、工具、业务统一到 SDK 层中。


集成工程负责集成 Lyft、Ola、GrabTaxi 项目,所有业务项目提供 AAR,由集成工程整体打包对外发布。

3.3 SDK 工程组件化拆分

为了解决组件之间耦合,防止后续问题加剧,同时方便协同开发和更好的复用,将 SDK 工程组件化拆分如下:



SDK 整体拆分为 Business Library 和 Util Library 两大部分,主要依据是是否可以独立于我们业务,他们间不允许反向依赖。每个部分包含若干组件,每个组件都以 Module 形式存在。

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
滴滴国际化项目 Android 端演进,一个小例子彻底搞懂Android的MVP模式到底是什么