Android 和 Java 技术栈差异

技术栈差异

要做一个 Android 开发或者 Java 开发 “攻城狮”,你大概需要的知识图谱如下(图是根据自己的认知整理的,有不详尽甚至错误的地方望指出):

Android 开发:

image.png

Java 应用开发:

image.png

可以看到,从大类看其实都是通的,无非是基础的框架、扩展的库或中间件、以及一些列的发布、监控等支撑平台,套路上无论做什么技术估计都是这样吧,但偏向性却有本质的区别。面向客户端的 Android Framework 核心解决的问题是事件交互、生命周期、视图绘制问题、处理人机交互的逻辑,而 Java 服务端常用的 Spring 框架核心更关心服务之间的耦合、依赖、面向大规模集群扩展的能力。基础框架不同,必然类库、中间件也会有本质的区别,几乎就没有共性了,这些由设计思路带来的不同势必也要求开发的同学需要在转换开发角色时转换思考方向。

思考问题的角度转变

翻看以前的代码,记得刚从 C/C++ 学 Java 的时候,还在学生的时代,总会喜欢一个 main 函数带着一群 static 方法来实现主流程,又到后来学 Python 用于一些数据分析和脚本处理,也总是焦虑没有地方声明变量类型,对于 a = {} 这样的 map 声明方式也很不习惯,所以,不光是 do as Romas,Think as Romas 才是转变中最重要的东西,不仅仅只是换了一些库和工具。

动态性

动态性曾经是客户端最为看中的能力,从热修复到动态 dex loader,到 RN、Weex、Dinamic 一系列动态能力的建设,可以说是面试必考题。无论是 Android 菜鸟还是 Android 专家,都要让你聊一聊你知道的动态技术方案以及他们之间的区别,几个大厂之间的热修复方案对比更是每个 Android Dev 都需要准备的分享 PPT,Android 如此,IOS 也不例外,直到 IOS 禁止了动态加载的能力。

对于客户端来讲,发布周期与服务端有着较大的区别,按照之前我们在手淘的集成经验,Android 端覆盖 80% 的用户大概需要 3-5 天的时间。早些年更慢,因为还没有 App 商店的统一静默升级,还需要在各个应用市场更新或者推送更新,简直五花八门,用户也不胜其烦。IOS 会稍微好一些,古早就有了应用市场,但一个更新周期毕竟还是远远大于后端的周期,应用发布都是以分钟最多是小时级别记。这样的区别导致客户端的开发过程必须要考虑:

  • 使用动态框架,从应急修复到动态发布,一方面是应急,另一方面是加快版本迭代和收敛效率。那么,设计的业务框架、写的组件是不是有动态修改、扩展的可能性,是否存在编译、混淆优化导致无法热修复的风险,是设计和开发过程中要考虑的点。
  • 无法挽回的发布。不仅仅是因为面向用户,只要发出去的版本有问题,大概率是没有时间和机会挽回的,容易出较大的舆情和故障,所以客户端的测试工作也会比较辛苦,全功能的回归是发布前必走的流程。

但这些问题在 Java 应用上很不显著,虽然也有热部署的框架,但仅仅也是为了部署效率,并不会作为核心的能力提供。

兼容性

同样是因为迭代周期长,并且无法做到真正全量更新,客户端还会面临一个较大的问题就是版本兼容。目前 Android 已经更新到 11 了,但市场上也不排除有 4.x 的版本,同样,App 发展到 X 版本了,市场上同样遍布这 1-N 的各个版本。版本覆盖后的数据兼容,特别是 sqlite 升级,会让 Android 的开发者们苦恼万分,也经常容易出现问题而导致启动闪退,被迫让用户重新安装。同样的问题在服务端还是比较少出现的,唯一可能的就是协议的变更,但往往也可以在短时间内进行共存和迁移。

除了端上数据的兼容性,另一个兼容性就是 API 及设备的兼容性,特别在 2.x 到 4.x 的年代。同样的视图实现在不同的 Android 机器上、在不同的 API Level 上都可能出现不同的表现,修改方案也往往故此失彼,往往一次修改完就得所有主流机型回归一遍,对于在 Android 中重 UI 的开发同学,简直有摔手机的冲动。当然现在 API 日渐完善,compat 包也解决了很多兼容问题,开发体验已有质的飞跃。从这方面说,Java 应用面临的问题又要简单不少,部署环境有问题?用 Docker 虚拟化!简直乐无边!

内存管理

但服务端应用并不意味着更简单。老实说,去年差点没被线上 FullGC 弄死。一大波流量进来,持续的 FullGC 导致集群假死,大量的服务超时引来客户投诉,重启扩容都无法解决,还得靠找到问题的根源后才能解决。FullGC 是 Java 应用常见的问题,但在客户端是完全不需要关注的。客户端分配给 App 的内存通常只会有 128M~256M,与服务端动辄几个 G 的内存管理不能同日而语,并不过分关心 GC,除非是在极致的性能优化场景,更别说是用 G1 还是 CMS 了(当然 Android 也没有)。通常只关心泄露和 OOM,毕竟 OOM 才是客户端唯一的内存杀手,所以才有了大波的图片加载库,来解决对象的内存管理问题,毕竟一个 App 在你的手机里存活不太可能以天计,在前台的时间更是少之又少,不太必要考虑长时间运行下的累积问题。

状态问题

客户端的状态一般都是保存在页面本身的。页面、视图作为一个对象,获取数据,渲染,展现给用户,并负责与用户交互,反馈修改页面状态等一系列动作,几乎把一个页面内的所有行为状态都封闭了起来,形成交互对象内的强耦合。但 Java Beans 可能并不是这么想,所有的 Beans 原则上都是无状态的,数据由专门的 db 或中心存储,这也是分布式系统的基本要求,这点上是设计思维的最大转变。

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java