使用RxJava的一个很大的优势就是线程的灵活切换,特别是Android开发,工作线程请求,主线程监听,这已经是最普通的常规操作,但是Activity和Fragment都是有生命周期的,如何让我们的请求能在页面销毁时及时方便的撤销,可以说开发者的一个小小痛点。但是不想偷懒的码农不是三好码农,我将尝试逐步解决这个痛点,最后的结果可能还有优化的空间,重点是中间的思考过程。

一个常见的失败的例子

模拟Http请求,延迟10s后发射,不用多言

在数据延迟结束前将Activity 关闭,这时候我们未做任何处理,结果自然是内存泄漏,因为我们的监听Consumer 在这里是一个匿名内部类,所以它会持有外部Activity 的引用,自然就泄漏了

问题发现了,我们就要想办法解决,第一个方法很容易想到,在Activity的onDestory方法中,判断任务是否被撤销,未撤销则执行撤销

Activity生命周期中撤销

这样做确实可以,但是麻烦,而且不容易扩展,如果有多个请求,就要写多行dispose的代码,代码维护起来很痛苦,显然这个不是我们想要的。

尝试做抽象

我们的目标很明确,就是不需要Activity或者Fragment宿主持有Disposable对象去执行dispose方法,我们还是从RxJava的操作符中尝试找答案。

takeUtil

官方文档解释说明:“discard any items emitted by an Observable after a second Observable emits an item or terminates”,拙劣的翻译:“一个Observable丢弃掉所有发射的数据 在 第二个Observable发射了数据或者终止 之后”,看图解更直观

可以看到图中第二个Observable发射了数据0之后,第一个Observable之后发射的数据(从6开始)都被丢弃了,这个特性刚好非常适合我们的需求,通过第一个Observable A takeUtil 第二个Observable B,就可以通过给B发送数据 来达到终止A发射数据的需求。我们一般用Observable.create操作符创建的 Observable 都是在ObservableOnSubscriber中通过 emitter来发射数据,如果需要在外部发射数据,就需要利用新的对象Subject. RxJava 提供了 4种 Subject

  • AsyncSubject
  • BehaviorSubject
  • PublishSubject
  • ReplaySubject

我们重点说BehaviorSubject,它的特性是,最终发射的数据是在它被订阅之前发射的最后一条数据+被订阅后发射的所有数据,它能够保存一条被订阅前发射的最新一条数据,可以防止我们的异步请求漏掉activity或者fragment的生命周期。

compose

如果让我们的所有Observable都自己新建一个BehaviorSubject,然后去调用takeUtil,然后在activity或者Fragment的生命周期回调中调用 BehaviorSubject.onNext,这样就太麻烦,甚至比我们上面的第一种方法更繁琐,我们想到了compose操作符,它的作用就是对Observable进行一对一的转换,它的一个常规操作就是用来简化重复代码,比如SubscribeOn,ObserverOn 这样的公式代码, 当然我们在我们这里也可以用它,所以我们自然想到新建一个RxLifeCycleActivity基类,然后新建一个BehaviorSubject对象,新建一个bind方法,供子类调用绑定生命周期,然后在OnDestory中调用BehaviorSubject的onNext方法

然后在子类中就可以像这样调用来绑定生命周期

对生命周期粒度进行细化

上面实现了请求在onDestory中一定会被终止,但是如果需求希望在onPause或者onStop中进行终止呢,所以 需要对生命周期事件进行细化,首先新建一个RxLifeCycleEvent枚举

然后在RxLifeCycleActivity中的生命周期回调用发送不同的事件 然后新建一个新的方法bindUntil,第二个参数是想要终止的条件事件,我们对BehaviorSubject接收到的数据进行一次filter,发射条件是接收到的事件>终止的条件事件

更高的要求

这样我们的轮子算是一个能正常跑了,但是使用起来还是比较痛苦,因为要继承RxLifeCycleActivity类,而且还要实现一个RxLifeCycleFragment供 Fragment页面继承,这种改动的侵入性太强了。 这里可以参考Glide 图片下载的 生命周期监听的思路,给activity 或者 fragment 添加一个 空布局的RxLifeCycleFragment,然后将我们之前的RxLifeCycleActivity中的逻辑移植到这个fragment中,

然后新建一个门面类RxLifeCycle,添加bind(Activity activity) 方法和bindUtil(Activity activity, RxLifeCycleEvent event)方法

这样我们的轮子基本就完成了,绑定fragment的代码大家可以看源码,毕竟水平有限,肯定还有很多优化的空间,最后附上项目地址。

参考: 知乎 RxLifeCycle

转载于:https://juejin.im/post/5b724e47f265da27fb52662a

学着造轮子-RxLifeCycle相关推荐

  1. 经常造轮子的 AI 工程师水平通常不会太差

    题图 | 邵姺画 引子 | 造轮子还是不造轮子,这是一个问题 理查德·费曼教授去世后,人们在他的黑板上发现了 What I cannot create, I do not understand 这句话 ...

  2. 51年被发现9次,陶哲轩证明的公式成了重复造轮子?事情并没有这么简单

    晓查 栗子 发自 凹非寺  量子位 报道 | 公众号 QbitAI 在科学探索的过程中,"重复造轮子"从来就不新鲜. 最知名如牛顿和莱布尼茨,各自独立发明了微积分:而计算机领域,也 ...

  3. 你们应该听说过”w8ay“这个ID吧!一个喜欢造轮子的小子

    他是w8scan.w9scan.w11scan.airbug的作者.他也是hack-requests的开发者.他在2018 Kcon以学生的身份展示了"自动化扫描工具".他也在Fr ...

  4. 造轮子是什么意思_程序员为什么热衷于造轮子,升职加薪吗?

    作者:小傅哥 博客: https://bugstack.cn- 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 哪个架构师没造过轮子? 你想过这样一件事吗? 是先具备能力在安排职位,还是先安排 ...

  5. 精读《怎么用 React Hooks 造轮子》

    1 引言 上周的 精读<React Hooks> 已经实现了对 React Hooks 的基本认知,也许你也看了 React Hooks 基本实现剖析(就是数组),但理解实现原理就可以用好 ...

  6. 来一起造轮子:手写 Vue3 reactivity 模块

    最近和一个猎头聊天,说到现在前端供需脱节的境况.一方面用人方招不到想要的中高级前端,另一方面市场上有大量初级前端薪资要不上价. 特别是用 Vue 框架的,因为好上手,所以很多人将 Vue 作为入门框架 ...

  7. 程序员如何通过造轮子走向人生巅峰?

    前言:你所做的事情,也许暂时看不到成果.但不要灰心,你不是没有成长,而是在扎根. 程序员圈经常流行的一句话:"不要重复造轮子".在计算机领域,我们将封装好的组件.库,叫做轮子.因为 ...

  8. 程序员该造轮子吗,造轮子能升职加薪吗?

    持续坚持原创输出,点击蓝字关注我吧 作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!???? 目录 一.前言 二.我造过的轮子 1. RPC 通 ...

  9. 造轮子 Websocket 现在就 Go

    造轮子 Websocket 现在就 Go MD: 2019‎年‎12‎月17‎日,‏‎03:45:10 笔者坚果有幸从事软件开发,一直都是兴趣驱动的工作.第一次接触计算机是 1999 年后的事,我用来 ...

最新文章

  1. 详解Pattern类和Matcher类
  2. xshell 上传 下载文件
  3. python界面设计-python图形化界面设计tkinter
  4. vue根据索引删除数组中的一个对象_Vue实现动态添加或者删除对象和对象数组的操作方法...
  5. 直击Titan图数据库:如何提升25%+的反欺诈检测效率?
  6. 10个出色的NoSQL数据库
  7. 计算机导论的试题,计算机导论试题
  8. c++11中的for简化用法
  9. 已知两点经纬度求球面最短距离的公式推导过程(几何法加向量法)
  10. vNext之旅(1):从概念和基础开始
  11. eclipse ARM/AARCH64版本下载
  12. java开发spc分析软件,告诉你们什么才叫真的SPC软件?
  13. dell电脑如何安装ubuntu系统_如何在 Dell PC 上安装 Ubuntu Linux
  14. python 3des加密_python3使用3des加密
  15. web编辑器——百度UEditor编辑器使用教程与使用方法
  16. cad延伸命令怎么用_CAD缩放怎么用,CAD缩放图文教程
  17. PS工作记录——图片元素复制,智能抠图
  18. mysql 3306无法访问_Mysql 3306端口无法被远程机器访问
  19. WebView 拦截广告 简单实现
  20. 【Tushare 大数据社区——解救你的财经数据需求】

热门文章

  1. 干掉状态:从session到token
  2. Java程序员从笨鸟到菜鸟之(九十一)跟我学jquery(七)jquery动画大体验
  3. Python matplotlib pyplot中title() xlabel() ylabel()无法显示在中文(方框乱码)的解决办法
  4. 《Effective C++》读书笔记(第一部分)
  5. 两个命令把 Vim 打造成 Python IDE
  6. Spark编程指南(Python版)
  7. 跟我一起写 Makefile(六)
  8. 部分手机配置信息及价格
  9. Git使用方法——原创
  10. 【干货】浅谈分布式数据库中间件之分库分表