我为什么嫌弃RxJava,不再推荐使用?
热文导读| 点击标题阅读
互联网寒冬下,程序员如何突围提升自己?
华为蒙洪OS方舟编译器编译工具正式发布, 附源码下载
字节跳动Android高工面试记,已拿 Offer 入职!
作者: W_BinaryTree
链接 : https://juejin.im/post/5cd04b6e51882540e53fdfa2
距离上一次更新也有一段时间了,其实这篇文章我早就想写,碍于一直没来得及总结(懒)。所以一直没有成文。来总结一下我RxJava遇到的坑,或者说我为什么不在推荐使用RxJava。相信熟悉或者关注我的朋友,绝大多数都是因为RxJava。所以看到这个标题你已经会惊讶。作为RxJava坚定的拥护者,或者说自干五?为什么突然不再支持RxJava了呢?
先讲讲历史
在我的文章中已经讲过很多次RxJava诞生之初就是因为异步。再后来借鉴LINQ的思想借用Monad的力量使得 Rx可以使用操作符进行组合将各种复杂的请求简单化。可以说,RxJava的设计初衷就是围绕着Asyhconization和Composition。当年的Netflix也是为了增加服务器的性能和吞吐量来编写RxJava并开源。才使得RxJava问世。详细关于这段可以参考我的知乎回答:你会在实际工作中使用 rxjava 吗?
(https://www.zhihu.com/question/53151203/answer/164427549)
再聊聊异步
在那个RxJava刚刚火爆的年代,那是一个荒蛮的年代。我们在异步方面资源匮乏,手头仅有ThreadPool,AsyncTask和Handler这些基础封装的异步库。所以当我们看见RxJava这个新奇的小玩意,当我们看到异步还可以这么简单,轻而易举的解决Concurrency问题。我们当然如获至宝。
而我们现在选择就更多了,无论是Java 8本身提供的CompletableFuture
。还是后起之秀Kotlin上的Coroutine
,还有Android 上官方提供的LiveData
(这里说下:虽然本质上线程管理仍需用户自己,但是常见的比如Room数据库,Retrofit等等都有现成的LiveDataAdapter,实际上并不需要我们过多操心线程问题)。相比之下,RxJava优势并不那么明显,相反劣势却很突出。
RxJava 门槛太高
相信多数Android开发者并没有了解过或者说深入了解过(我自己也没深入了解过)函数式相关的知识。但是如果不了解这些,那么而几乎可以说不可能融会贯通RxJava的一些概念。举个例子,一个很著名的Googler: Yigit Boyar。 也就是每次IO的那个大胡子,他的代表作有很多。比如RecyclerView,再比如Architecture Component。这样一个Android界名人,水平怎么也有平均以上。但是他在实现LiveData和RxJava适配的时候,同样出现了由于理解上出的问题,造成错误的实现方式。 RxJava的门槛过于高,就连我自己推广这么久,自己也不敢说对RxJava了解有多深刻。经常在常见操作符的使用中出现了或多或少的unexpected behavior。再者,无论国内国外的RxJava教程水平都参差不齐。新手很难鉴别哪些人说的是对的哪些人说的是错误的。在这样鱼龙混杂的条件下学好这个高门槛的异步库更是变得难上加难。很多教程在自己没有精通的情况下,很容易误导其他人(包括我自己的文章)。
投入高,收获少
虽然这点存疑,因为我自己钻研RxJava之后确实觉得收获很大,尤其是经由RxJava窥探了函数式的大门。但是功利的看,RxJava在解决异步处理这个问题上,的确是投入高,收获少。异步问题是Android开发必不可少的一个环节,可以说掌握异步应该是成为入门Android开发的敲门砖。而RxJava归根到底是通过响应式的方式配合Monad来解决异步问题。但是仅仅为了解决异步问题,学习并精通RxJava并不是必不可少的。相反,精通RxJava需要大量时间和精力,在现在异步编程逐步完善的情况下,完全没有必要。
你永远无法预测你同事的RxJava水平
上面几点可能有点抽象,而这点和接下来的几点都是我在实际工作中遇到的实际情况。首先就是你并不能预测或者要求你的同事RxJava到达什么样的水平。我之前的公司使用了一个简单的类redux框架。其中RxJava是核心部分,他承载了中间render层和view层的连接。具体关于这个架构可以看我这里的项目实例:Twivy(https://github.com/wbinarytree/Twivy)。在Review同事的代码之后,我才发现RxJava还能这么玩?
各种奇思妙想的作用让我不得不佩服法国同事的丰富想象力。而这些错误使用就像一颗颗定时炸弹一样埋在代码里。随时可能爆炸。但是反过来一想,并不是所有人都像我一样喜欢研究RxJava。他们可能仅仅是因为使用了这个架构而接触Rx。而RxJava的掌握并不是一个Android开发的必要条件。他完全可以一点RxJava也不会也成为一个优秀的Android Developer。
RxJava的行为并不可预
RxJava还有一大毛病就是光看方法名你很难知道他的真正意思。在初学RxJava时候,两个一直纠缠不清的问题就是 map
和 flatMap
的区别。还有 flatMap
和 concatMap
的区别。简单的讲 map
是一对一, flatMap
是一对N的map然后在进行 flatten
操作。还有些教程直接写出 flatMap
无序, concatMap
有序。其实这些都只是简单总结,而实际的行为照着相差甚远。比如 flatMap
在第一个error的时候会不会继续继续触发第二个?如果我想继续,将如何操作?再比如 concatMap
在遇到第一个 Observable
不会中断的时候,怎么继续下一个?
这些都几乎是要看源码或者做多次实验对比才能得出结论的问题,而实际工作中并不想去因为这个工具而去浪费太多时间,得不偿失。但是如果不做,就像前文提到的定时炸弹一样。上线直接增加错误几率。
RxJava太容易出错
Uncle Ben 说过:
with great power comes great responsibility. RxJava就是这样。在简单易用的同时他太容易被滥用了。我在实际工作中碰到的例子:
val stationId = "5bCP6Iqx"val statoin:Observable<Station> = staionRepo.getStationById(stationId)val stationLine:Observable<StationLine> = station.flatMap{station ->stationRepo.getLine(station)}return Observable.merge(station.map{it.toUiModel()}, stationLine.map{it.toUiModel()})val statoin:Observable<Station> = staionRepo.getStationById(stationId)val stationLine:Observable<StationLine> = station.flatMap{station ->stationRepo.getLine(station)}
return Observable.merge(station.map{it.toUiModel()}, stationLine.map{it.toUiModel()})
乍一看,这几行代码并没有错。这个Bug还是后台反馈给我的说为什么android每次都会发两个一模一样的请求?其实问题就出在stationLine和station并没有共享结果。造成了每次请求都要发两次。修改后的代码:
val stationId = "5bCP6bif"val statoin:Observable<Station> = staionRepo.getStationById(stationId)return station.publish{selector ->Observable.merge(selector.map{it.toUiModel()}, selector.flatMap{station -> stationRepo.getLine(station)} .map{it.toUiModel()})}val statoin:Observable<Station> = staionRepo.getStationById(stationId)
return station.publish{selector ->Observable.merge(selector.map{it.toUiModel()}, selector.flatMap{station -> stationRepo.getLine(station)} .map{it.toUiModel()})}
RxJava还是过于理想化了
RxJava承诺出一个完美的异步世界,一切异步操作由上游控制,下游只需要思考如何处理,并不关心数据来源。而实际过程中,这个过程还是过于理想化了。最直接的例子就是BackPressure的出现。在数据量足够庞大时,缓存池并不能及时缓存所有生产的数据,造成越积越多最终OOM。也即是所谓的BackPressure。再者,函数式中的Monad来包裹异步这个操作还是过于复杂了,看过RxJava的朋友都应该清楚。某些很简单的操作符在实现起来其实非常复杂。
追踪数据十分困难,很容易掉入很难Debug的情况。而且虽然RxJava的文档是我见过少有写的非常出色的库,但是很多操作符如果不读通源码,仅仅从Java Doc和Method Signature来观察,并不清楚期待的行为是什么。就算知道,在一些特殊情况如何处理,仍是一个未知结果。同时RxJava虽然解放了上游控制权力的,也引入了不安全性。如果上游出现了非预想的问题,下游将很难处理。
其次,RxJava为了这个理想化的世界,引入了太多的overhead。无论是每个操作符都要生成一个新的Observable实例还是蹦床模式(https://github.com/ReactiveX/RxJava/wiki/Writing-operators-for-2.0#serialization)的异步解决方案。都生成了太多的Object在堆中存放。这种overhead在轻量级应用,或者一些小型异步处理比如数据埋点等等行为中,都显得过于庞大。
RxJava起于异步,却也不单单是异步
Rx在被Erik Meijer 提出的时候,确实是由同步的Iterable推导,由主动拉取数据改为被动接受数据(可参考我之前的文章:一篇不太一样的RxJava介绍[https://juejin.im/post/5a2549576fb9a04519696d45 ])。但是在加入函数是Monad的概念之后,RxJava作为响应式数据流,应用在了更多Callback base的场景中。在Android这种GUI平台下尤为出色。多数基于Redux结构的Android架构都或多或少基于RxJava。或者借鉴RxJava的思想。比如Airbnb推出的MvRx。还有Google在18年io中当作Sample App做出的Sunflower,大量使用LiveData
。而LiveData
无疑也是大量借鉴了RxJava的思想。
总结:RxJava虽然优秀,但并不适合所有人
即使RxJava有且不仅限于我说的上述几个问题,但无疑RxJava仍是一个划时代的优秀的异步框架。但是优秀并不代表适合所有人,我在之前推广RxJava,认为这样的异步基础应该是每一个Android开发者必不可少的知识点。但实际工作使用两年之后,我觉得这并不实际,也不必要。RxJava的水平并不能映射一个Android Dev的开发水平,反之,一个高水平的Android Dev也并不一定对RxJava了解多少。在这样的前提下,再加上入门门槛高,易出错,行为不好预期等等缺点下。在团队没有RxJava Expert的情况下我更倾向于直接弃用RxJava,转为更容易使用的异步框架和响应式数据流。我在入职新公司的的时候,邮件里写了这样一句:
engineering is about trade off
RxJava便是这样一个库,甲之蜜糖,乙之砒霜。用的好RxJava,他是一个利器,根本离不开。用不好,他就是你身边的定时炸弹,随时爆炸却又很难拆解。
更多学习和讨论,欢迎加入我们的知识星球,这里有1000+小伙伴,让你的学习不寂寞~·
看完本文有收获?请转发分享给更多人
我们的知识星球第三期开期了,已达到1100人了,能连续做三期已很不容易了,有很多老用户续期,目前续期率达到50%,说明了大家对我们的知识星球还是很认可的,欢迎大家加入尽早我们的知识星球,更多星球信息参见:
欢迎加入Java和Android架构社群
如何进阶成为Java的Android版和架构师?
说两件事
微信扫描或者点击上方二维码领取的Android \ Python的\ AI \的Java等高级进阶资源
更多学习资料点击下面的“阅读原文 ”获取
谢谢老板,点个好看↓
我为什么嫌弃RxJava,不再推荐使用?相关推荐
- 王垠:不再推荐 Haskell
0 前言 在看论文的时候,发现用了Haskell,本来想温故一下,发现有篇文章写的不错,转过来,大家分享一下.以下是原文. 在之前的一篇博文里,我推荐从函数式语言入手掌握程序语言.推荐的两种语言是 S ...
- rxjava获取异步请求的结果_我为什么不再推荐用 RxJava
点击"开发者技术前线",选择"星标?" 13:21 在看|星标|留言, 真爱 作者: W_BinaryTreehttps://juejin.im/post/5 ...
- 我为什么不再推荐RxJava
距离上一次更新也有一段时间了,其实这篇文章我早就想写,碍于一直没来得及总结(懒).所以一直没有成文.来总结一下我RxJava遇到的坑,或者说我为什么不在推荐使用RxJava. 相信熟悉或者关注我的朋友 ...
- 为什么我不再推荐大家去注册今日神评自媒体平台?
当今日神评出来的,有不少小伙伴说,又一个有保底收益的自媒体平台横空出世啦,自媒体人不够用了. 刚开始的时候,我也比较好奇说又有一个保底的自媒体平台可以入驻了,就赶紧入驻吧!事实证明,入驻还是比较简单的 ...
- 为什么我不再推荐使用 MVC 框架?
来源:鹅是程序猿 toutiao.com/i6763420080542843399 所以V层是否还有必要? 所以我认为目前的多终端环境下,新的划分方式如下: 标题是不是有点耸人听闻,不过我并不是标题党 ...
- 强烈推荐16 款牛逼的 IDEA 插件,让你开发速度飞起来!
当前最新版IDEA版本是2020.1.随着IDEA版本的升级,有些插件不再支持,而有些插件变成了收费插件,这些插件将不再推荐. 以下列举的,都是亲测可以在2020.1版本的IDEA中使用的插件. go ...
- 用大白话讲解RxJava原理
近日外媒报道称,Google 其应用商店 Play Store 一次下架了超过 600 个违规 App:其中中国.印度以及新加坡为本次大规模下架 App 开发者前三的国家,来自中国的猎豹移动所开发的 ...
- python编辑器_初学Python这几款编辑器,推荐你安装
编程这个东西是真的奇妙.对于懂得的人来说,会觉得这个工具是多么的好用.有趣,而对于小白来说,就如同大山一样.其实这个都可以理解,大家都是这样过来的.那么接下来千锋武汉Python培训小编就说一下Pyt ...
- h3c 路由器 刷第三方固件_图文版*许迎果 第201期 双11路由器型号推荐之刷机路由篇...
哈喽大家好,我是许迎果. 一年一度的双11大型剁手节马上就要到了,相信有不少小伙伴已经在摩拳擦掌,跃跃欲试,逐渐充实自己的购物车.不过话说回来,从南京到北京,买的没有卖的精,双11的套路也是越来越多, ...
最新文章
- java modbus通讯协议_物联通讯协议一(Modbus)
- tcp wrapper
- TF-IDF与余弦相似性的应用(三):自动摘要
- 【赫夫曼树详解】赫夫曼树简介及java代码实现-数据结构07
- 为什么数据中心不能给乡镇带来新的就业机会
- JZOJ 5253. 排列与交换
- Java实现单链表的反转
- hibernate配置
- 简单的文本片段替换器
- linux路由表生成,路由表(FIB)内容的生成(一)
- 我就不信发不出去,工 作 时候用的,来啊=》模板下载
- ELK在广告系统监控中的应用 及 Elasticsearch简介
- 被严重 “高估” 的未来
- 58沈剑_一分钟专栏
- CSRF漏洞利用以及防御手段(详细解释)
- 如何获得的office 365 年卡
- 云计算机平台 显示器,云桌面
- diff 算法深入一下?
- 普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法
- Excel 写入复制模板,写入数据并下载
热门文章
- 外贸邮件群发邮箱,看看哪个更适合你的公司吧
- 如何检测远程主机上的某个端口是否开启?
- 【计算机组成原理】溢出
- cocos creater_画线
- 一年每人薅450美金羊毛!斯坦福学生用AI让航空公司蓝瘦香菇
- 如何提高逻辑思维能力笔记
- 邮件发送时间怎么修改 python_Python_定时自动发送邮件
- pdf免费转换工具,只需记住这3款就够了
- linux默认csh修改命令,修改shell 将当前shell(默认是bash B SHELL )改为csh C SHELL...
- SpringCloudOpenFeign奇淫技巧