很久没更新CSDN博客了,不是转行了,而是实在太忙,生活/小孩/工作,中年男人的时间已经不是自己说了算。平时也是非常简单地记录一下编程的经验,算不上文章,所以转向了自己搭建的博客。由于只是简单记录一些零散代码,发出来没头没尾的,怕被喷,所以大部分文章也是自己可见。闲话扯远了,今天想聊一聊Android应用开发10+年的一些新感悟。
以下是郭霖前辈公众号转载的文章《Google 为何设计了如此难用的 ArrayMap》下一位读者的留言,实实在在戳中了我这个安卓老鸟的内心:
还有另外几个吐槽比较有代表性:
确实,Google负责Android API的大神们给我们Android开发者留下了太多的坑,别的不说,最基本的权限申请,已经改了无数遍,即使是推出了AndroidX和Jetpack套件,权限这一块的兼容性仍然是非常复杂,开发者苦不堪言,想说爱你真的难。
回首Android开发经历,我曾经偏爱MVP,因为P层可以拿到View/Activity的引用,直接更新UI,非常方便。但随着开发经验的积累,以及谷歌API的限制,在P层持有View层引用始终有很大的内存泄漏风险,所以我更赞成MVVM了。比如在View销毁了,但对象没销毁的情况,举个例子:Navigation + Fragment的场景,就避不开onDestroyView()执行了,但onDestroy()却没执行,虽然MVP也可以在onDestroyView()的时候去清空P层的View引用,但数据恢复还是不太方便,诸如屏幕旋转等场景,要去恢复对话框等数据是比较棘手的。将数据处理和界面分开确实是更合理的编程思维(虽然底层还是通过观察者注册监听等建立联系),对于我们应用开发而言,代码也是更加清晰。其实MVVM非常经典,可以参考桌面开发的WPF,即使后面微软也推出了WinUI3,但还是有很多人在用WPF,而且WPF功能非常强大,足够支撑大部分复杂的桌面开发。
而对于后面出现的MVI,我感觉没有必要,当然如果说的是Compose的MVI,这是后话,等下再谈。
就在我认为谷歌会继续优化Jetpack套件,小修小改,潜心做好API兼容性工作的时候,它却想搞些不一样的东西,其中最让我反感的就是依赖注入框架。在我的记忆里,依赖注入在后台框架应用比较广泛,如Spring MVC这些。而对于大多数Android应用,真的有必要引入依赖注入吗?开发者真的懒到连new XXX()都不想写?在我看来,Dagger/Dagger2/Hilt,甚至后来的Koin,90%的项目都没必要使用,尤其是Dagger,极其复杂,连官方自己的例子都错误百出,引入这些依赖注入框架不仅没有让项目更容易维护,反而给项目带来很多隐患,极大增加了项目维护的难度。
继续折腾传统原生开发还是不过瘾,谷歌又换了个方向。在Android MVC的年代,谷歌就盯上了跨平台这块蛋糕,那时主要是Phonegap和ReactNative这些前端框架在掐架,于是谷歌搞了个名为Flutter的框架。针对移动前端这块,由于Flutter对IOS的兼容性之差,个人的观点是,如果IOS开发不采用Flutter,那我Android开发为什么不直接使用原生开发?性能更高,开发更快。如果没有好的脚手架,Flutter那地狱一般的嵌套,真让人抓狂。唯一的优势可能符合小公司老板的经济利益,招一个开发,用Flutter,把Android和IOS的活都给干了。实际的情况是,IOS端根本没几个人用Flutter,导致国内很多都是用Flutter在做Android开发,基本上都是搭积木的形式搞出来的半成品。所以前段时间传言Flutter团队解散,我其实没有多惊讶,甚至感觉理所当然。
Kotlin:JetBrains是我爹,Google是我干爹。Kotlin作为谷歌的官方开发语言,确实给Android开发者带来了更多的便利,空安全,可选参数,扩展函数…然后谷歌推出了Compose。谷歌的官网是这样介绍Compose的:一种用于构建原生 Android 界面的新式工具包。然而,谷歌似乎投入太多精力在这个工具包了,甚至还在惦记着跨平台那块蛋糕,让Compose也支持多平台。
在我这个老鸟看来,不是不想学新技术,也不是不看好跨平台,而是跨平台从来就只有H5,术业有专攻,原生(Compose)还是不要去赶这趟浑水了,Flutter就是前车之鉴。
同时,谷歌在官网催促我们迁移到KSP(虽然它没有说Kapt是否已经Deprecated)。另外,里面还有一个提醒:
Note: While not a traditionally-included library dependency, Data Binding also uses an annotation processor to provide its functionality, and KSP support for Data Binding is not planned. You can mitigate the impact of kapt on your build by isolating the usages of Data Binding to separate modules.
这无疑是给原生党泼了一盆冷水:大家赶紧迁移到KSP–>KSP不支持DataBinding–>我们也没有计划让KSP支持DataBinding,因为我们都投入到Compose里去了,用DataBinding的都是老项目,老项目不会去迁移到KSP,新项目都是用Compose,所以我们暂时不在乎DataBinding。
虽然DataBinding不能代表MVVM,也不能代表原生开发,但却是原生开发+MVVM非常重要的一个组件,尤其是在界面数据非常多的时候,DataBinding会比手动赋值方便很多。在我看来,对DataBinding还有念想的开发者只能等待,等待两种情况:1.Compose冲击跨平台失败,谷歌对Compose的热情熄灭,发现Compose再怎么折腾也只是一个UI工具包,坑太多,填不完,弃坑,将Compose标记为Deprecated。当然,这种可能性比较小,至少短期内,3/5年内不太可能。
2.Compose回归UI工具包的身份,作为一个辅助嵌入到传统原生开发。Compose确实可以作为工具包和传统原生开发混用,但目前应该没什么人会这样做,会显得不伦不类+失去了Compose的优势(如切换主题/统一屏幕适配等)。所以,第二种可能性在短时间内也不太可能被广泛采用,3/5年内不太可能。
如果让我新开一个公司级别的项目,我还是会选择MVVM,而不是Compose,理由:丰富的传统原生开发经验,有把握迅速开发各种界面和稳定的功能,有信心保证代码的质量。在我看来,Compose就像是绕了个圈,且处在圈的最后一节,这个圈就是:在代码里写界面–MVC–MVP–MVVM–在界面里写代码–如此循环。我相信谷歌最终还是会回归传统原生开发MVVM,就如同很多桌面开发觉得还是WPF舒服。等到那天,谷歌也许会重新给KSP安排上DataBinding,又或者,KSP也已经被废弃,只是到那天,我们可能早已不做Android移动开发了…