RxJava如何结合观察者与链式处理
RxJava如何结合观察者与链式处理
Author: Dorae
Date: 2018年12月3日17:10:31
转载请注明出处
一、概述
首先问自己几个问题,如果非常清楚这几个问题的目的与答案,那么恭喜你,不用继续往下看了-_-。
- RxJava是干什么的;
- 链式调用中当存在数个Observable.subscribeOn()时的处理方式;
- 链式调用中当存在数个Observable.observeOn()时的处理方式;
- 数据是如何经过操作符进行的处理。
回顾
观察者模式
如图1-1所示

图 1-1
Java8的stream
二、RxJava是什么
一款为了简化异步调用,且功能比较全面的框架。
三、RxJava如何结合了观察者模式与链式处理
参见Java8中的sink链,在RxJava中同样实现了链式处理。如代码片段code1-1所示,我们对其结构进行分析:
code1-1
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("Dorae");
}
})
.filter(e -> e.contains("o"))
.map(e -> "AfterMap: " + e)
.filter(e -> e.contains("D"))
.subscribe(new Observer<String>() {
@Override
public void onNext(@NonNull String o) {
System.out.println("观察者 onNext: " + o);
}
@Override
public void onSubscribe(Disposable d) {
System.out.println("观察者onSubscribe: " + d + "### " + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
1、首先看下其输出结果:
观察者onSubscribe: io.reactivex.internal.operators.observable.ObservableFilter$FilterObserver@52d455b8### main
观察者 onNext: AfterMap: Dorae
2、现在来对如何输出这段结果进行分析
首先了解下RxJava中的几种基本角色:
- Observable,是RxJava描述的事件流,可以说其与Observer构成了RxJava的基础。在链式调用中,事件从创建到加工到最后被Observer接受,其实就是由一条Observerable链串起来的。
- Observer,RxJava中的订阅者,也就是需要对事件进行响应的一个角色。其实除了我们通常自己实现的一个Observer,在链中的每一步都会产生一个Observer,然后这些Observer构成一条链,最终完成整个链的计算。
- ObservableOnSubscribe,整个事件流的源头,通常需要我们自己实现,其依赖一个Emitter。
- Emitter,可以将其理解为触发器,推动整个流程的运转。
- Scheduler,这个其实不用太过关心,RxJava用其封装了Thread,用于完成线程切换等任务。
是不是感觉上边的一堆废话非常枯燥?先上一张RxJava的核心结构,如图3-1所示。

图 3-1
现在我们再来看看code1-1,其最终形成的Observable链如图3-2所示,每次调用map、filter等操作,都会生成一个新对象,并且保持了一个对上游的引用(用于生成Observer链)。

图 3-2
Observer链如图3-3所示,整个事件流程由CreateEmitter触发,最终交由我们的实现Observer$1处理。

图 3-3
看了上边几张图之后,是不是感觉清晰了很多?那么让我们进一步看下Rxjava如何完成了一键线程切换。
四、RxJava如何实现线程切换
通常我们使用RxJava的线程切换功能时,只需要在调用链中加上一句subscribeOn()或observeOn(),其中Scheduler如上所述,其实就是一个包装了ThreadPool的调度器。那么我们先来看下相关源码。
1、subscribeOn
如代码code4-1所示,为subscribeOn的核心代码。很明显,其中在新线程中只是简单的直接调用了source,也就是说这里之后的所有操作均在一个新线程中进行,和单线程并没有什么区别。
code 4-1
public final Observable<T> subscribeOn(Scheduler scheduler) {
return new ObservableSubscribeOn<T>() {
@Override
public void subscribeActual(final Observer<? super T> observer) {
scheduler.createWorker().schedule(new SubscribeTask() {
@Override
public void run() {
source.subscribe(e);
}
});
}
};
}
2、observeOn
如代码段code4-2所示,为observeOn的核心逻辑,可以看出其在订阅阶段(生成Observer链的阶段)还是在当前线程执行,只有触发之后,到了ObserverOn的Observer的节点时才会真正的切换到新线程。
code 4-2
public final Observable<T> observeOn(Scheduler scheduler) {
return new ObservableOnSubscribe<T>() {
@Override
public void subscribeActual(@NonNull Observer<Object> e) {
source.subscribe(new Observer<T>() {
@Override
public void onNext(T var1) {
scheduler.createWorker().schedule(new Runnable() {
@Override
public void run() {
e.onNext(var1);
}
});
}
});
}
};
}
多次Observable.subscribeOn()、多次Observable.observeOn()会发生什么
通过上述code4-1、code4-2的分析,是不是可以推断出当多次subscribeOn时会发生什么?没错,虽然每次subscribeOn都会产生一次线程切换,但是真正起作用的只有最开始的一次subscribeOn,也就相当于只在最初的位置调用了subscribeOn;对于observeOn也是类似,每次都会产生新线程,但是每次都会产生一定的影响,也就是每个线程都承担了一部分工作。
小结
通过本文,我们可以简要了解到RxJava的基本原理,但是对于其丰富的api还需要在实践中进行磨合。但是,RxJava既然作为一个异步框架,其必然有一定的局限,比如其切换线程时无法阻塞当前线程(这种对于Android等需要渲染或者网络IO的需求来说非常适用),但是对于常见的服务端业务来说,还需要额外引入阻塞当前线程的操作(因为大部分的server代码还是单线程模型),倘若完全不用线程切换在服务端强行引入,可能会得不偿失。个人更推荐Java8的CompletableFuture。
参考
RxJava如何结合观察者与链式处理的更多相关文章
- PHP设计模式:类自动载入、PSR-0规范、链式操作、11种面向对象设计模式实现和使用、OOP的基本原则和自动加载配置
一.类自动载入 SPL函数 (standard php librarys) 类自动载入,尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_registe ...
- 用php实现一个简单的链式操作
最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...
- C#用链式方法表达循环嵌套
情节故事得有情节,不喜欢情节的朋友可看第1版代码,然后直接跳至“三.想要链式写法” 一.起缘 故事缘于一位朋友的一道题: 朋友四人玩LOL游戏.第一局,分别选择位置:中单,上单,ADC,辅助:第二局新 ...
- 由表单验证说起,关于在C#中尝试链式编程的实践
在web开发中必不可少的会遇到表单验证的问题,为避免数据在写入到数据库时出现异常,一般比较安全的做法是前端会先做一次验证,通过后把数据提交到后端再验证一次,因为仅仅靠前端验证是不安全的,有太多的htt ...
- 如何写 JS 的链式调用 ---》JS 设计模式《----方法的链式调用
1.以$ 函数为例.通常返回一个HTML元素或一个元素集合. 代码如下: function $(){ var elements = []; ;i<arguments.length;i++){ v ...
- iOS 链式编程探索(Masonry)
看了几篇关于链式编程的文章,还是理解的不透彻,我想这可能是因为我自己对block掌握的不熟练. 我已经明白了,所以,和大家分享一下我的理解!如有问题,麻烦大家指出! 直接看代码吧!关键的注释都有. 我 ...
- jQuery插件编写及链式编程模型小结
JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQu ...
- ASP.NET MVC学前篇之扩展方法、链式编程
ASP.NET MVC学前篇之扩展方法.链式编程 前言 目的没有别的,就是介绍几点在ASP.NETMVC 用到C#语言特性,还有一些其他琐碎的知识点,强行的划分一个范围的话,只能说都跟MVC有关,有的 ...
- 原生JS实现jquery的链式编程。
这是我根据之前遇到的一个面试题,题目:用原生JS实现$("#ct").on("click",fn).attr("id"). 然后看了篇jqu ...
随机推荐
- Get 和 Post 使用篇(1)
1.Post 请求发送方式 实例: const string sResponseEncoding = "gb2312"; //测试文本信息 string postText = &q ...
- ACM_Hailstone HOTPO
Hailstone HOTPO Time Limit: 2000/1000ms (Java/Others) Problem Description: The hailstone sequence is ...
- Git管理多个远程分支
在此目录下使用GIT要注意一下几点: 因为这个目录是管理远程多个不同的分支的项目,所以使用GIT之前确认一下几点: 打开git bash,使用命令:git config –list查看目前本地的目录文 ...
- 389 Find the Difference 找不同
给定两个字符串 s 和 t,它们只包含小写字母.字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母.请找出在 t 中被添加的字母.示例:输入:s = "abcd"t = ...
- 2017-12-04HTML table布局
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- Python之Pandas中Series、DataFrame实践
Python之Pandas中Series.DataFrame实践 1. pandas的数据结构Series 1.1 Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一 ...
- UVM基础之------uvm phases机制
代码的书写顺序会影响代码的实现,在不同的时间做不同的事情,这是UVM phase的设计哲学,UVM phase提供了一个通用的TB phase 解决方案.支持显示的隐式的同步方案,运行时刻的线程控制和 ...
- js中获取class封装
1.封装 //封装getClass function getClass(tagName,className) //获得标签名为tagName,类名className的元素 { if(document. ...
- Farseer.net轻量级开源框架 入门篇:逻辑层的选择
导航 目 录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 入门篇: 入门篇:增.删.改.查操作演示 下一篇:Farseer.net轻量级开源框架 入门 ...
- [Windows Server 2012] 更换PHP版本方法
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:更换PHP ...