经过研究,发现了安卓开发的低效性
安卓翻身论破产的后续
安卓开发简直就是低效的代名词。以前只是 UI 写起来麻烦,现在 UI 写起来简单了,但是整个系统的复杂度令人难以忍受。想要做安卓开发,不仅要懂业务逻辑,还要成为半个 Gradle 专家、半个系统适配专家和半个架构师,外加还要忍受垃圾的就业市场。
实在不行咱们还是抄一抄前端框架吧,虽然经常有人吐槽前端天天造轮子,但是好歹人家从 IDE 插件、包管理器、工具链到开发都是越来越好用,我实在看不出来安卓开发哪里有进步。
Android Studio 和 Gradle 更新了 5 年,几乎没有任何实用的功能变化。 而且这俩还是出了名的内存和 CPU 消耗大户,电脑风扇狂转是家常便饭,慢的一批的同时还特别难用。Gradle 版本需要和 AGP、IDE 版本对应才能正常编译成功,版本范围还得去官网摸,这是人能想出来的设计吗?几乎 99% 从 GitHub 拉下来的开源安卓项目都无法正常编译。
一个小小的安卓开发,技术栈极其割裂。 语言层面 Kotlin、Java 并行,UI 层面 XML、Compose、Flutter 并行,SDK 层面 Support 库和 Jetpack 并行,外加狗屎的 Gradle,直接把大多数入门的小白拍在岸上。
官方天天就鼓捣那破 B 设计模式,“最佳实践”最多不超过 2 年就变老黄历。 光我用过的就有 MVC、MVP、MVVM 和 MVI,而且设计模式的“最佳实践”也在不断变化:早期的 Android MVVM 每个 UI 状态都用
ObservableField,后来又用LiveData,谷歌现在推荐的最佳实践又变成了用一个不可变的 UI 状态,通过StateFlow来管理,我内心真的是一万个草尼玛奔腾。状态管理越来越复杂。 从 MVVM 开始:
ViewModel、LiveData、StateFlow、SharedFlow、生命周期、冷热流、背压……对于 MVI 架构,还需要引入 Event、State、Side Effect 等一整套概念,即使是一个简单的操作,样板代码也非常多,心智负担越来越高。干什么都要传 Context,能不能学学 iOS 把你那 Context 解耦了? 安卓每次传 Context 都像在做题:
- 在 Activity 里,用
this还是getApplicationContext()? - 在 Fragment 里,用
getContext()还是requireContext()还是getActivity()? - 构造子 View,用
getContext()? - 给工具类传入一个 Context 试试……不好,内存泄露了。
想象一下,你能忍受 JS 变成这样吗:
window对象有好几个版本,一个是“全局版”,一个是“页面版”,还有一个是“组件版”。每次调用一个 API 前,都必须先决定是传入window对象还是一个代表当前<div>的特殊对象,选错了就会导致内存泄漏或页面崩溃。- 在 Activity 里,用
增量编译是个笑话。 Google 推出了各种优化手段,理论上增量编译应该很快,但实际上,稍微修改一下常量、资源文件、或者某个模块的公共 API,就可能导致大范围的重新编译,WTF?你永远不知道下一次按下“Run”按钮是 10 秒还是 10 分钟。Activity 热更新和 Jetpack Compose 的 Preview 功能偶尔会无故失败或加载极慢,完全不告诉你为啥,白白浪费时间。
SDK 依托答辩。 打个比方,实现一个后台任务,有
WorkManager、Foreground Service、AlarmManager、BroadcastN 种选择方式,然而当你都实现了一遍后,发现原来都是不可靠的,后台任务是否能存活还是得看操作系统的脸色。开发者和厂商被迫研究各种“黑科技”,最终形成了“后台保活”这个畸形的子领域,与 Google 的政策背道而驰。依赖注入几乎变成标配。 因为谷歌的垃圾设计,注解、组件、作用域,对于新人开发直接一脸懵逼。
无尽的 API 废弃与迁移成本。 虽然 Google 努力在推新版本,但市场上 Android 8、9、10、11、12、13、14、15 同时存在,且占有率都不低。很多曾经被官方大力推广的 API 和库,短时间内就被废弃。一个新 API,你不仅要用,还要为数亿无法升级的用户写兼容性代码,代码中充斥大量的
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XXX),丑陋程度堪比 Go 的if err != nil。国内厂商定制(魔改)地狱是比系统版本碎片化更恐怖的存在,同一个标准 Android API,在不同厂商的 ROM 上可能有截然不同的行为,你不仅要适配 Android 版本,还要适配 MIUI 版本、EMUI 版本。Activity/Fragment 销毁重建机制。 应用切了一下后台,Activity 被销毁了;旋转一下屏幕,Activity 又被销毁了;到点了手机自动切换到夜间护眼主题,Activity 又双叒叕被销毁了,nm 的用户的应用还在前台呢你就销毁!你销毁了,为什么要我来恢复状态???这种非功能性的开发复杂度,与业务逻辑无关,纯粹由平台和生态引起。大量的、本应由框架透明处理的复杂性,直接暴露给了应用层开发者,迫使开发者花费巨量精力去进行防御性编程。
页面导航和栈管理堪称一团乱麻。 在 Jetpack Navigation Component 出现之前更甚,虽然现在变简单些了,但是旧项目也没机会迁移了。开发者需要手动管理
FragmentTransaction、处理各种launchMode、Intent Flag,极其容易出错。获取NavHost、NavController,不利用依赖注入的情况下也很麻烦,完全没有前端框架的useRoute方便。就连测试工程师都没办法愉快摸鱼。 UI 测试编写起来繁琐、运行起来极慢且极其不稳定,测试经常因为各种奇怪的原因(动画、网络延迟、模拟器状态)失败,维护成本非常高。一旦涉及到需要 Android Framework 的集成测试或 UI 测试,就必须依赖模拟器或真机,完全没有办法在 CI/CD 环境中高效、稳定地运行测试。
作为开发工具来说,AS 就是个烂货,把这句话重复十三遍。开发这么多年了,用过 VS、Delphi、C++ Builder、XCode、Eclipse、嵌入式 IDE 等各种工具,从使用体验来说:VS 无疑是最优秀的开发工具(没有之一),当然早期的 Delphi、C++ Builder 等也不差。
AS 难用的主要原因
1. 依赖库和包的实时下载性
这不仅仅是 AS 的问题,很多现代特别是互联网开发工具的特性。由于现在网络流量非常便宜和方便,而且开发环境的多样化,所以很多现代开发工具安装时都是只安装基本用到的库,其他的库都是在需要用到的时候,通过配置动态下载和导入。这种方式优势是:节约开发工具占用的存储空间,即开即用。
但劣势也明显:如果网络有问题,或者依赖的库比较多、库文件比较大,库中心版本管理不好,那么动态下载和导入就会很消耗时间。而 Google 正好这几点都没有做好,一个基本工程依赖的库毕竟多,而且还有各种版本兼容性问题,加上 ZZ 因素被 Qiang,劣势的几个因素都占全了,所以库和 JDK 的安装下载这一步就挡住了很多人了。
对比下来,VS 就做得好很多,安装的时候可以选择需要的组件,如果不懂就一股脑儿全选,这样安装的时候虽然消耗的时间长一点,但一旦安装完成后,就再也不用担心缺库少包了,打开工程都基本上就能直接编译了。
2. 工程配置架构(Gradle)
Gradle 这玩意儿的缺点很多人都提到了,这里就不多说了,其中最本质的原因就是 AS 中关于 Workspace 和 Project 的配置,Google 一开始就是没有完整的架构设计的,基本上拿到 Gradle 随便搭上点什么就发布了,最大的问题是:兼容性设计,或者说兼容性完全没有设计。
有了新增关键字和接口,都不会考虑如何兼容旧版本,所以开发者经常会遇到各种 Gradle 和 JDK 的版本兼容性问题。加上 Android 系统大版本的不断迭代和升级,也依赖于对应的 Gradle 和 JDK 版本,这就导致开发者在各种版本兼容性之间操作。
3. SDK、依赖库的接口和版本混乱
这个不仅仅是 AS 工具的问题,而是整个 Android 系统设计的混乱。Android 系统大版本升级,通常都要更新 SDK 版本,还得对应的 Gradle 和 JDK 版本对应。Android 系统内部库迭代也是如此,就以 UI 组件库为例,早期有 Android Support Library,后来是 AndroidX,现在又在推 Kotlin 和 Jetpack Compose,基本上过一段时间就推一些新的框架库(可能内部 KPI 压力吧,总得出点活)。而开发者很多早期项目还得沿用旧库,这在维护迭代上会有不少困难。
通常打开一个正常的 AS 工程代码,要能使得项目跑起来,开发者得考虑到:
- 有没有下载对应版本的 SDK,并且进行配置。
- 使用的 Gradle 版本是否支持,太旧的版本、甚至太新的版本都不行。
- 对应的 JDK 是否安装,JDK 版本要跟 Gradle 配套,太高、太低也不行。
- AS 的版本与 Gradle 是否匹配,一些新版本 AS 直接不支持太旧的 Gradle 编译。
- 科学的确保 Gradle 配置中,所有依赖库都能正常同步到本地。代码中只是普通依赖库还好,如果依赖于一些小众开源项目的话,甚至可能要换不同的魔法进行上网尝试。
各个不同的开发者,上面这些配置可能各不一样,所以就出现其它答主提到的:网上下载的开源项目 99% 跑不起来。要解决这些问题,无非两种方案:
方案一:在不改动任何配置和代码的情况下,安装相应版本的工具
- 根据项目配置安装对应版本的 Gradle。
- 根据 Gradle 的版本,确认本地安装对应版本的 JDK。
- 确保当前 AS 版本支持 Gradle,不行的话得换 AS 版本。这特么不是下载工程和代码,是不是还得下载一套开发工具?
方案二:修改相应的配置,适应开发者当前的开发环境
这里就是需要了解 Gradle 的原理,能够熟练进行配置和修改。例如:可以调整依赖库下载的源地址,更新 Gradle 版本之类等。其实对于开发者来说:这些问题都不大。
但是关键:有很多项目的代码,是依赖于特定 Gradle 编译的,开发者还得回到第一种情况更新相应配置。例如:有些项目中代码必须依赖于 Gradle 6.0.0 版本编译,不能使用新版本 Gradle 编译,当你配置这个版本的 Gradle 后发现,JDK 版本不匹配了,于是你又安装了对应版本的 JDK,然后编译时发现 AS 已经不支持 Gradle 6.0.0 了,于是你还得重新安装一个旧版本的 AS。
综上,各种版本配置和兼容性问题,才是 AS 最大的问题。 特别是对于早期项目来说,当时的 Gradle、JDK、AS、SDK 等都旧版本,要进行维护和迭代,只能切换回旧版本工具。这一点在 VS 上就做得很好,VS 新版本几乎都能打开旧版本的工程配置文件,打开后可以直接编译运行。除了个别版本差异太大,打开时会提示工程文件版本太旧,询问是否转换成新版本工程问题。通常会提供一键直接生成新版本工程文件,然后开发者之间打开新工程文件,也可以直接编译运行。想想当年 M$ 的 Windows 之所以能统治市场这么多年,最重要的一点就是确保版本的前向兼容性。
还有就是 Gradle 为什么这么难用却能流行起来?
都 2020 年了,还是经常给人抛一个 failed,一个构建工具,入门难度高,到现在还稀里糊涂。一个构建工具连个向下兼容都做不到,贵团队开发可真太难了呢,一个项目一个版本,一个版本一个进程,一次 100m 的下载体验,易用性上 Maven 甩你 100 条街。看了架构也不觉得有什么亮点,一个打包工具,起个守护进程也是没谁了,没办法嘛 jvm,没办法嘛贵团队可能只会 java 系,自从入行两年以来,最让我烦躁的工具和框架,没有之一,学 rust 都没感觉自己如此的无能,更让我感到惊讶的是这鬼东西,为什么能流行起来,看来是我程序员还没入门吗?
我之前一直用 maven,来到新公司后开始使用 gradle。
我不知道 gradle 的设计者是怎么想的,为什么一个构建工具,要搞的这么复杂,如果不深入研究研究,gradle 很难玩的转,APl 说变就变,遇到个报错,百度出来的都不一定能用,因为版本之间 API 不兼容。
maven 的那一坨 xml,虽然不好看,但是格式统一,也严谨,错了就是错了,而 gradle 呢,是用的 groovy、kotlin 去写各种 task,task 有什么参数,调用的内置函数会传什么参数,并不会明示,只能百度、看官方文档,想开车是吧,先学发动机怎么造。
如果让我花点时间学习一门编程语言,我很开心,但是让我花很多时间在一个构建工具上,说实话,我觉得很浪费。
我不喜欢 xml,巨讨厌 xml,我在努力滴把所用到的开源项目去 xml 化。
但是,我在日常的构建工具中,则是:能用 maven,就用 maven,不用 gradle。
原因很简单,gradle 的脚本,很难直接拷贝过来就 run 起来,基本上都会出各种乱七八糟的问题。
也就是说,gradle 会把构建工具给复杂化,如果你的项目本身,重心不在构建工具上的时候,并且 maven 能够很好解决你的问题的时候,那还是 maven 吧。
maven 的pom.xml,很少发生过拷贝过来林北不能用的情况。
那什么时候用 Gradle 呢?
- 一般是类库开发时候用 gradle,有些时候不得不用 gradle。
- 比如 gradle 可以用来构建 c++ 和 swift 的项目,maven 基本上就只针对 java/jvm 上那些语言了。
- gradle 上自定义脚本比较方便,所以涉及到 aot, graal 等大量自定义非常规配置的项目,也需要 gradle。
- 前者的例子就是 javafx 的
build.gradle,有 5000 多行,看得我头疼,因为涉及到 c++。 - 后者的例子就是 spring 现在开始推荐缺省用 gradle,他们的说法说是用 gradle 搞 native image 简单。
- 前者的例子就是 javafx 的
- 安卓开发用 gradle 也是有传统的,因为安卓本身就涉及到大量 native, gui 和 aot 的东西,相比之下,spring 和 javafx 都还是后来的了。
但是如果你只是想整个项目,做点简单的业务,没有太多定制的东西,也不想浪费时间在构建工具上,那么你就用 maven 就好了,这样可以避开脚本。
脚本的特点就是会让一个人把简单的问题复杂化,这不仅仅是 gradle/groovy,javascript, python 什么也是一样的,别人写的脚本,管他什么语言写的,我是连看都不想看,有看的功夫,我不如自己写一个,估计还更快,脚本就适合那种,用完就丢掉的破烂需求。
要维护代码的话,选择静态类型是基本素养,ide 遇到静态类型也能变得很智能,遇到动态类型的 ide 卡得你怀疑电脑是不是坏掉了。
初心者如果没有什么特别追求的话,完全可以从 maven 入手。然后等你开始看源码,开始给开源项目贡献你代码的时候,再开始 gradle 不迟。
已经研究了一个月的 gradle 了,说说我的感受。
难用,非常难用,脚本里面写一大堆东西,完全不知道什么意思。对,我确实不懂,学了一个月还是不懂。我太笨了。
很多简单的需求搞不定,可能是我不知道。
我有这样一个需求,公司自己写了一些库,有一个自己项目的
xxx-parent,里面定义了些dependencyManagement,这些东西非常有用,因为它可以解决其它项目的版本依赖问题。同时还把spring-boot-dependenciesimport 进来了这样我们的项目在建立的时候,只需要将这个xxx-parent作为项目的 parent 引入进来就好了。xxx-parent还定义了一些插件的默认配置,这些配置运行的很好。
我尝试使用 gradle 复刻这些功能,我发先我完全不知道如何下手,我看了很久的文档,我完全可以按照教程构建自己的应用,但就是不能完成我上述的需求。
后来我观察了 spring-boot 的构建代码,我发现要些插件,是的…应该是要写一些插件,抱歉,我对它一无所知,在 maven 中,很容易完成这些功能。或者一些其它的需求,应该也要编写插件才能完成,也就是说,你需要编写大量的插件。
就我的使用来看,gradle 也许足够灵活,也许可以完成各种灵活的构建任务。但也需要开发人员对它非常熟悉才行。但 gradle 的脚本我是看不明白的,有时候某个变量或者方法完全不知道什么意思,IDE 中也跳转不过去。
maven 不灵活,或者说非常僵硬,但它的功能通常够用了,也正是这种僵硬,使得出错的可能性比较小,问题也好定位。
作为一个程序员,我不讨厌 xml,xml 也许臃肿,但严谨的结构,使得它不容易出错。
gradle 的另一个优势可能是快,它确实比较快。但我仍然喜欢 maven,直到我彻底掌握 gradle 之前。也许在我的职业生涯中,或许永远都不能掌握它,谁知道呢?
附:好像 android 的用 gradle 的比较多,spring boot 本身的构建也转 gradle 了。但写后台代码的大部分还是用的 maven 的样子。
reported from : coolapk@囧路西法
- 标题: 经过研究,发现了安卓开发的低效性
- 作者: XuanRan
- 创建于 : 2025-12-12 19:08:01
- 链接: https://blog.xuanran.cc/2025/12/12/经过研究,发现了安卓开发的低效性/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。