Kotlin-风险高、RxJava-不老,Android-原生开发现状分析!

这些在市场公关层面更受关注,如果 Jetpack 在 2020 年申请独立 IPO,我都不会感到惊讶。

不过,说真的,尝试向自己生态系统内的开发者“销售”API 的想法,我觉得存在一些问题,比如说,谁会想看搜索出来第一个就是 ViewModel 广告呢?

总而言之,Jetpack 只是 AndroidX 库的一个聚合,所以在前面写到的 AndroidX 的内容,在很大的程度上也适用于 Jetpack。在后面的内容中,我将单独讨论其中一些 API。

后台作业

在 Android 应用程序不在前台执行逻辑时,你可以有很多种方式来实现后台运行,这也是 Android 动态化的用例之一。如果你不引入 doze , SyncAdapter , CGMNetworkManager , FirebaseJobDispatcher , JobScheuler 和最近的 WorkManager,可以使用常规的启动服务(非绑定服务)来实现。这些都是 Google 提供的 API , 我可以说出所有的使用方式。当然,还有一些第三方库可以使用, 例如:Android-Job。

不过,Google 最近宣布,他们将围绕 WorkManager 来统一后台任务调度[3]。这听起来非常棒,我再也不用学习那么多后台调度的知识了,只是,不知道为什么,我好像以前在哪儿听到过这句话……

我们不管将来是否会统一使用 WorkManager,WorkManager 都还存在一些问题,比如可靠性。我不想在本文中解释为什么,但是请你一定要记住,如果你想在应用程序中使用 WorkManager,实现后台作业,一定要去读一下 dontkillmyapp.com 上的所有内容,并且要关注一下与 WorkManager 相关的 Google 问题列表[4]。

Android 的后台作业由于碎片化等原因,导致它们一团糟,而且还很不可靠。

在过去,我一直主张尽可能对数据和其它类型的后台处理进行同步。我或许是 SyncAdapter 最后的粉丝。今天,考虑到可靠性的问题,我建议,尽可能避免后台作业。如果你的老板一直坚持要使用这个功能,请将上面的链接发给他们,告诉他们,后台作业可能会需要数百小时的工作,才能实现,并且它带来的问题也会比它带来的好处多很多。

很多情况下,后台作业的需求是不可避免的。但是在大多数情况下,你都可以不使用它。虽然有时候会给用户带来一些不便,但是这可能是到目前为止的最佳方案。

数据库

在有关 SQLite ORMs 的内容里面,没有什么令人吃惊的内容—— Room 主宰着一切。Room 从 2.2.0 开始,添加增量注解解析支持。不过,请你一定要记住,你应用程序的架构不应该关心你使用的是什么样的 ORM 框架。说到 Room,“架构组件”也只是一个营销术语,并不是一个技术角色。

在 Android ORM 框架中,与 Room 竞争的主要是 SQLDelight。这是一个比 Room 老很多的库。但是据我所知,**在过去的一年里,它几乎被全部重写。****但新版本的 SQLDelight 只针对 Kotlin。**另一方面,SQLDelight 也支持 Kotlin Multiplatform,所以,随着 Kotlin 使用的增多,我预计, SQLDelight 的采用率也会随之增加。

顺便说一下,在 AndroidX 的命名空间下,也有 SQLite 的镜像。我不知道这个会有什么用处,但是如果你在应用程序中直接使用 SQLite,也可以对这个进行深入的研究。

此外,我们也不要忘记非关系型数据库,比如 Realm、Parse、Firebase、ObjectBox 等等 (其中一些,核心还是使用的 SQLite 来实现的),如果我没有记错的话,这些非关系型数据库中,大多数(甚至全部)都具有自动数据同步的功能。在之前有段时间里,它们非常地流行。但是现在,据我所知,已经不再流行了。也就是说,在短期内,我会持续关注非关系型数据库。

去年,我写了一个非常复杂的应用程序,对接了一个 Parse 的服务。这个 App 具有完全的离线支持,服务端本地化,用户指定的系统和语言设定,复杂的多媒体系统等功能。我在 Android 端上使用了 Parse 的 SDK。除了一些小的 WTF 以外,其他体验都非常棒。如果你们公司有很多后台开发人员,或者说你需要实现大量的服务端逻辑,这也许并不是最佳解决方案。但是对于仅仅只需要执行简单的 CRUD 操作的初创公司,这或许是一个不错的选择。

一个警告:如果你打算采用数据库即服务解决方案(如 Firebase),请你一定要关注长期使用的成本和影响。

外部存储

Android 外部存储发生了一个“很有意思”的变动。

如果,你在开发 App 的时候,把 Target API 调整为 29 及以上,之前获取 SD 卡文件的方法,现在都不能使用了,并且不会提示任何异常。现在,你需要使用 Android 存储访问框架来进行更细粒度的文件访问。不幸的是,Android 存储访问框架的工作原理与之前的读取方式完全不同,你可能需要对代码进行大量的重构,来实现新的文件访问和读取。

Google 原本希望在 Android 10 上,对所有的应用程序进行文件访问的限制,推广使用 Android 存储访问框架的方式进行文件访问。但是这个改动引起了社区内的强烈抗议,所以 Google 决定推迟推出这个功能。因此,现在即使你的应用程序在 Target API 29 及以上,也可以设置为在“Legacy”模式下可读取文件。不过,有可能在 Android 的下一个版本,不管你设置的 Target API 为多少,都会限制应用程序使用新的作用域访问模式。

到目前为止,我也还没有更新我应用程序的文件访问方式。但是从互联网上的讨论来看,实现新的文件访问方式是一项很具挑战的任务,虽然你的应用程序在“Legacy”模式下,没有任何异常,但是我建议你最好从现在开始,着手对代码进行重构和测试,以防发生不可控的事情。

Shared Preferences

在几周前,AndroidX 家族增加了一个新的库,这条提交信息写道:

新的库用来替换 SharedPreferences,新库的名称还没有确定下来,这次提交只是为了评审和设计文档(请自行申请设计文档)。

现在还没有什么值得担心的。不过,从长远来看,SharedPreferences 会被废弃掉,取而代之,使用新的库来实现类似的功能。

与 SharedPreferences 不同的是,这个新的库默认情况下使用的是异步的方式。换句话说,如果你需要取某个值,你需要实现回调,通过这个回调才能拿到值。

如果你对这种异步回调的原理感兴趣,你可以去看看 StackOverflow 上的这个回答。Reddit 的一个用户 Tolriq 分享了他们的 App 遇到的一个 SharedPreferences 的 Bug,这个问题影响了万分之一的月活用户。对于一般的应用程序来说,这个问题并没有什么明显的影响。但在一些需要高可靠性的应用上,就显得很不可靠了。举个例子,如果在 Android 汽车上,应用程序的无响应和崩溃会引起驾驶员的注意力被分散,这将有可能导致出现交通意外。

依赖注入

在依赖注入领域,最大的新闻莫过于 Dagger-Android 被弃用,有两点需要强调一下,首先我所说的弃用,不是正式的弃用,因为官方并没有发布声明。其次,Dagger-Android 并不是指整个 Dagger 2 框架,只是指其中相对比较新的部分。详细细节可以看我的另一篇文章[8]。

在 Android 领域也存在其他的依赖注入框架,但是我不认为他们会比 Dagger 更好。值得一提的是,Koin 是一个不错的依赖注入框架,但是我依然觉得它也不会引起多大的潮流。它之所以会被采用,无非是这两个原因,一个是,它拥有比 Dagger 好很多的文档,降低了很大的学习成本。第二个是它基于 Kotlin 进行编写,因为 Kotlin 的热度,给它也带来了不少的关注。到目前为止,Kotlin 的热潮几乎已经全部过去了,所以,我预测,Koin 的关注也将会逐渐减少。

不管这些框架如何发展,手动依赖注入的发展都会很缓慢。

Google 声称:随着应用程序的增大,手动依赖注入的成本会出现指数级增长。但是我并不这么认为,我觉得 Google 既不了解 “指数” 的含义,也没有实际去“衡量”过任何东西。这个申明的内容是错误的,我希望 Google 不再使用这种方式误导社区。

事实上,这种手动依赖注入在后端比较常见(尤其是微服务中,你并不想在每个服务中都添加对注入框架的依赖),也可以正常的工作。在后端,反射被经常用到,所以后端的依赖注入框架并不需要解析编译时的代码。

在 Android 上,解决方案与后端有一些不同,我们几乎不会用反射方案的依赖注入框架,所以就只剩下 Dagger 可以用了。其实,反射虽然会影响性能,但是在大多数项目,都是可以用的。我的意思并不是建议你们使用反射方案的依赖注入框架,这个选择并非是非黑即白的,你需要按照你的要求来进行选择。

无论如何,Android 领域上, Dagger 作为依赖注入框架的现行标准,我们所有人都在使用它。尽管 Google 在宣传上,对 Dagger 的使用成本使用漂亮的绿色图形进行展示,但是 Dagger 使用成本在实际上依然会随着时间增长而快速增长。越来越多的代码,在编译构建的时候需要花费更多的时间;你的开发人员越多,代码编译的次数就越多。当然,所有的开发人员都需要学习如何使用 Dagger , 这本身就是一项很大的成本。

换句话说,**虽然 Dagger 可以减少项目中编写的代码,但是需要花更多的时间去培训新人,在编译上花费更多的时候。**所以,对大型项目来说,使用 Dagger 会更耗时。

在一个大型项目中,编译耗时会逐渐成为生产力的瓶颈。当然, Dagger 也提供了很多优秀新的功能来帮助你优化编译时间,但前提是,你需要知道如何使用这些工具。读到这里,我相信你对手动依赖注入会很感兴趣。

数据绑定

作为一个 Android 开发者,都知道在写布局的时候,会经常调用 findViewById() 这个方法。DataBinding 诞生就是为了取代掉这个模板方法。老实说,在使用 findViewById 的时候,我并没有遇到过任何问题,虽然希望摆脱掉它,但我并不认为使用 DataBinding 就是一个更合理的方式。有一个好消息,很快我们就可以使用 ViewBinding 来摆脱 findViewById 了,也不需要使用 DataBinding。

说句实话,我不相信 DataBinding。对于它想解决的问题来说,这种方案在过于复杂。在使用 DataBinding 的时候,需要把代码逻辑放到 XML 布局中,这听起来很不错,但是经验丰富的开发人员都不会这么做,这个做法也是 Databinding 的另一个缺点。

早在 2016 年 11 月的时候,那个时候 Google 还在大肆宣传 DataBinding。我在 StackOverflow 的回答中作了如下预测:

我可以非常自信地预测:DataBinding 不会成为行业标准。DataBinding 可以带来短期收益,但是从长远来看,它将会使代码变得不可维护。一旦 Databinding 被长期使用,它的缺点就会暴露出来,将来它一定会被废弃掉。

我没有统计过使用 DataBinding 的项目,但是很明显,它没有成为行业标准。我从来没有在自己的项目中使用过它,也很少看到其他开发者使用。据我猜测,当 ViewBinding 逐渐成熟,并且被广泛采用,DataBinding 将会作为一个“传统”框架,大量地被引用到。

状态保存

自从引入 ViewModel 架构组件以来,在 Android 应用程序中,当配置发生更改,保存与恢复状态的逻辑,就变成了一个烂摊子,没有人去管理。虽然这样子说有点过分,但是我觉得,这已经是我最温和的表达方式了。

Gabor Varadi(又叫 Zhuinden)在 Reddit 论坛中描述了 ViewModel 引入带来的问题,我不需要再去写一遍了。再次强调,不推荐使用 onRetainCustomNonConfigurationInstance(),推荐使用 ViewModel。

在帖子的末尾,Gabor 作了一些预测:

你知道吗?Fragment 状态保存的方法已经被弃用了。

在我看来,废弃 Fragment 状态保存的方法是非常好的主意,众所周知, Fragment 的 onAttach() 和 onDetach() 方法就是为了支持状态保存的,现在废弃了状态保存的方法,那这两个方法也可以被废弃掉,并且这样子可以简化 Fragment 的生命周期。我长期以来都建议不保存 Fragments 的状态,忽略掉 onAttach 和 onDetach 方法,和我之前写的处理 Framgent 生命周期方法一致[12]。

尽管有很多理由表明,要废弃掉 Fragment 的状态保存,但是也不可能废弃掉 onRetainCustomNonConfigurationInstance(),这个可不是我说的,是 Jake Wharton 说的。在上面 Gabor 的帖子上,他的回复获得了最多的点赞。虽然我不太赞成 Jake 所说的话,但是我找不到更好的理由去说服自己。这个方法和 ViewModel 后台使用的原理完全一致,完全没有理由废弃掉它。

那我们应该怎么对待这些废弃的方法呢?Google 不管这些方法使用的技术方案和优势,都强制所有的 Andorid 应用迁移到 ViewModel。即使这些方案有可能优于 ViewModel 本身,他们也愿意放弃。听起来有点像是阴谋论吧。

我确实不喜欢保存非配置的状态,并且废弃掉对我没有任何影响,因为我从来都没有使用过它。事实上,大多数应用程序都不需要这些方法,当然,ViewModel 也不需要。我们需要处理状态改变的方法仅仅只有 onSaveInstanceState(Bundle) 这个方法。这个方法非常简单明了,可以同时处理保存和恢复的逻辑。所以,只要能用这种方式保存状态就可以了,我相信,我不是唯一一个使用这个方法的人。虽然 Google 对 ViewModel 进行了大量的营销宣传,但是对于很多经验丰富的开发者来说, ViewModel 还是太复杂了,我们有更简单有效的方法来处理状态存储。

如果 Google 别有用心,想强制所有项目使用 ViewModel , 那么它还将废弃掉 onSaveInstanceState(Bundle)方法。这听起来有点不可思议,如果将来真的这样发展,那说明我的基础理论是正确的。

考虑到 Android 的内存管理机制,Google 不可能在没有稳定的解决方案之前就废弃掉 onSaveInstanceState(Bundle) 。“幸运的是”,我们已经可以使用 ViewModel 来完成相关工作了。

我想,在一两年内,就能看到我的理论是否正确。

总而言之,如在本节开头所说,Android 状态保存将变成一个烂摊子。两年多前,我曾经写过 ViewModel 架构组件有害的文章[13]时,我就预测 ViewModel 会对保存与恢复状态的一点点造成影响。我所预测的都变成了现实,而且现在的情况比我曾经的预测更糟。

并发

在 Android 并发编程中,一个重要的 API 就是 AsyncTask, 不过它现在已经被弃用掉了。我之前已经写过很详细的文章分析过它了[14],在这里,将不再赘述。

下面我要说的内容,有可能会伤害很多读者,但是,请不要“恨”我。

**RxJava,是一个 Andorid 中常见的多线程框架。但是它现在将逐渐退出历史的舞台。**从 StackOverflow 的趋势图可以看出:

很多开发者对这个说法提出了质疑,他们反驳说这个数据不具有代表性,并且我们可以找到其它的理由来解释图上所发生的事情。他们所说可能是正确的,我个人本身也不是数据科学家。但是从图中我们可以看到,RxJava 与 AsnycTask 有相同的斜率。

**如果你没有时间去学习 RxJava 如何使用,并且你的项目中也没有使用过 RxJava,我建议你不要在你的项目中使用 RxJava。**事实上,我也一直不推荐使用 RxJava ,现在已经有数据支持我的这个观点了。

如果你的项目中使用了 RxJava,你也不用慌张,不需要紧急去重构你的项目。如果你的项目只有你一个人,或者整个项目组成员基本不会变动,保持项目现状就好了。但是你需要记住,**以后要招具有 RxJava 开发经验的人会越来越困难,新招开发人员可能需要学习使用 RxJava。**广泛使用 RxJava 的项目,在以后也会被认为"不酷",就像今天还在使用 AsyncTask 和 Loader 的项目一样。

我知道,很多 RxJava 的开发者都是 RxJava 骨灰级的粉丝,他们花了数周的时间去学习 RxJava,付出巨大的努力才说服队友在项目中使用 RxJava。现在我却在这里说 RxJava 已经过时了。我只能说,这不是我的个人意见,我只是对现有的情况进行分析,并根据我所看到的内容做出预测。我也有可能是错的。两军交战,不斩来使,请大家不要“攻击”我。

在 Kotlin 中,使用协程来实现多并发。最近使用协程实现了一些简单的用例,我发现它复杂、不稳定,甚至还有一些 Bug。

所有的人都在说,协程可以降低并发的复杂度,使用并发变得简单。我从来都不相信这句话,因为我知道并发从根本上来说就是很复杂的。我动手写过一些测试用例过后,据我的经验,我可以很自信的告诉你,协程不能使并变得简单。我认为,协程会增加复杂性,我建议你们谨慎使用他们。

在 Kotlin 中,协程将作为处理多线程的默认方式,如果你已经开始使用 Kotlin 进行开发,那么你应该花点时间,去学习一下,协程的使用。

据我所知,还有一个 Flow 框架,它是基于协程,添加了流运算符。在几个月之前,已经稳定了。所以现在也没啥好评价的。

Kotlin

现在,让我们来讨论一下 Kotlin 在 Android 领域的现状。根据我个人的经验来看,这是一个很敏感的话题,不论我所说的话有多么公正客观,都会有一些粉丝评价我所说的话是“Shit”。但从专业的角度来说,Kotlin 的话题是跳不过去的,所以,我要强调的是,这些内容只是我的个人观点,仅供参考。

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值