RxJava(一):响应式编程与Rx
一,响应式编程
响应式编程是一种关注于数据流(data streams)和变化传递(propagation of change)的异步编程方式。
1.1 异步编程
传统的编程方式是顺序执行的,必须在完成了上一个任务之后才能执行下一个任务。无论是提升机器的性能还是代码的性能,本质上都需要依赖上一个任务的完成。如果需要响应迅速,就得把同步执行的方式换成异步执行,方法执行变成消息发送。这样的优点是,当你有一堆不依赖于彼此的任务时,你可以同时启动所有任务,而不是等到每个任务完成后再启动下一个。这就是异步编程的方法,它是响应式编程的重要特性之一。
1.2 什么是数据流?
数据流是一种编程范式,数据流也被称为流处理或响应式编程。
传统上的程序指的是按照特定的顺序所执行的一系列操作,这通常被称为控制流或者命令式编程,这种程序侧重于命令,这与冯·诺依曼顺序编程的观点一致。
相比之下,数据流编程强调数据的传递,并将程序构建为一系列的连接。它显式地定义了输入和输出的连接操作,其功能类似于黑匣子。当一个操作的所有输入都有效时,它就会运行。因此,数据流语言本质上是并行的,可以在大型分布式系统中很好地工作。
举一个例子,App 的欢迎界面通常会需要加载广告,本地数据库等操作,这些都可以通过并行的方式来进行处理,全部成功之后才会进入主页,如下图:
通过这个例子,我们能够发现数据流的概念其实非常简单。它通过将不同的程序模块(每个程序模块可独立执行)连接起来,构建出并行的应用程序模型。
这里提到的不同的程序模块,在响应式编程中都被称为流。任何东西,数据库,共享内存,用户输入,变量等等都可以用流来表示。
1.3 变化传播
简单来说就是以一个数据流为输入,经过一系列的操作之后转换为另一个数据流,然后再分发给各个订阅者的过程。因为构建了数据之间的订阅依赖关系,将有助于自动传播改变的数据。
正是因为具备了以上这些特点,使用响应式编程可以很方便的表达数据流,同时相关的计算模型也能够自动变化并通过数据流进行传播。
响应式编程在处理 UI 事件,处理嵌套回调的异步事件,复杂的列表过滤等等方面都有很好的表现。
二,Reactive Extensions
Reactive Extensions(简称 ReactiveX) 是对响应式编程理念的一个实现。它最初是由微软的一个团队所开发的响应式扩展库(Reactive Extensions libraray,Rx),随后越来流行,目前已经支持了几乎全部的流行编程语言。
社区网站 reactivex.io 对其给出的定义是:
ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.
Rx 是一个使用可观测的序列来组成异步的、基于事件的程序的库。
定义中提到的序列即是指的数据序列,数据序列可以采用多种形式,例如来自文件或者Web服务的数据流,Web服务请求,系统通知或者用户输入的一系列事件。Rx 将所有这些数据序列表示为可观察序列 。应用程序可以订阅这些可观察序列,以在新数据到达时接收异步通知。(Rx 是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流)。
在响应式编程中,通过订阅数据流(在Rx中称为可观察序列)来向应用程序提供数据,应用程序在数据检索过程中是被动的:除了订阅了可观察的数据源之外,它不会主动轮询数据源,而只是对推送到它的数据做出反应。当流不再没有更多数据或者出错时,数据源也会向订阅者发送通知。
Reactive Extension采用的是这种推送(push)模式,它使得应用程序更具响应性。
ReactiveX 结合了观察者模式、迭代器模式和函数式编程的精华,为什么这么说呢?接着往下看:
现在假设有一个生产者 A 和一个消费者 B,生产者 A 持有一个可迭代的数据集合。当消费者 B 想要得到这个集合中的数据时,如果使用迭代器模式,消费者 B 就需要去从生产者 A 提供的迭代器中主动的读取数据,而如果使用的是观察者模式,数据将会由生产者 A 推送给消费者 B(本质上是使用回调之类的操作)。
这两种设计模式的区别就在于:迭代器模式中,消费者从生产者那里以同步的方式得到值,是消费者在控制何时取出数据。而在观察者模式中,生产者以异步的方式把值推给消费者,是生产者在控制消费者何时将接收到数据。
观察者模式适合使用在 UI 点击事件上,而迭代器模式的优势又在于能够使用一种更通用的方式来遍历不同类型的数据集合。
Reactive Extension(响应式扩展)结合了迭代器模式的思想,扩展了 GOF 观察者模式。简单来说就是 Rx 将可观察的数据类型和可迭代的数据类型统一成了一种名为 Observable 的新类型。
我们可以将 Observable 类视为与 Iterable 的 “拉” 操作功能相当的 “推” 操作。在 Iterable 中,消费者从生产者和线程中同步地提取值,而 Observable 中,只要值可用,生产者就会将值推送给消费者,这种方法更灵活,因为值可以同步或者异步到达。
Observables 和 Iterables(可迭代对象)共用一个相似的 API:在 Iterables 可以执行的许多操作也都同样可以在 Observables 上执行。不过由于 Observables 流的本质,所以并没有类似 Iterable.remove() 这样的方法。
Observables 支持异步推送多个值:
在传统的 GOF 观察者模式缺少了这样两个语义(或者说接口):
- 生产者在没有更多数据的时候能够发出通知。
- 生产者在发生错误的时候能够发出通知。
所以为了更好复用 Iterable 接口,Rx 的 Observable 类扩展了 GOF 观察者模式,将 Observable async/push(异步推送)与 Iterable sync/pull(同步拉取)关联了起来。引入了两个新接口:
- onCompleted():通知观察者Observable没有更多的数据。
- onError():观察者有错误出现了。
同时 Rx 还提供了一些操纵符,让你可以使用声明式的方式来组合这些序列,而无须关注底层的实现,比如线程、同步、线程安全、并发数据结构和非阻塞I/O。
正是这种 Observable 模型让开发者可以像使用集合数据一样操作数据流,并对数据流进行诸如过滤,查询,组合等一系列操作。
2.1 总结Rx模式
- 使用订阅模式
- 创建:Rx 可以方便的创建事件流和数据流
- 组合:Rx 使用查询式的操作符组合和变换数据流
- 监听:Rx可以订阅任何可观察的数据流并执行操作
- 简化代码
- 函数式风格:对可观察的数据流使用无副作用的输入/输出函数,避免程序里错综复杂的状态
- 简化代码:Rx 操作符有助于简化代码,避免嵌套
- 异常处理机制:传统的 try/catch 无法处理异步计算,Rx 提供了合适的错误处理机制
- 更容易处理同步与并发问题
参考:
ReactiveX/RxJava文档中文版
响应式编程
数据流
https://docs.microsoft.com/en-us/previous-versions/dotnet/reactive-extensions/hh242985(v=vs.103)
http://www.jonathanbeard.io/blog/2015/09/19/streaming-and-dataflow.html
http://reactivex.io/intro.html
RxJava(一):响应式编程与Rx的更多相关文章
- RxJava——响应式编程
自从06年开始,Rxandroid公司项目中陆续就开始使用它了,而它的基础是由Rxjava演变过来的,如今它也是越来越被广泛使用在商业项目中了,而做为"专业"的自己还是一直对它一知 ...
- 响应式编程(Reactive Programming)(Rx)介绍
很明显你是有兴趣学习这种被称作响应式编程的新技术才来看这篇文章的. 学习响应式编程是很困难的一个过程,特别是在缺乏优秀资料的前提下.刚开始学习时,我试过去找一些教程,并找到了为数不多的实用教程,但是它 ...
- Rx系列---响应式编程
Rx是ReactiveX的简称,翻译过来就是响应式编程 首先要先理清这么一个问题:Rxjava和我们平时写的程序有什么不同.相信稍微对Rxjava有点认知的朋友都会深深感受到用这种方式写的程序和我们一 ...
- 响应式编程知多少 | Rx.NET 了解下
1. 引言 An API for asynchronous programming with observable streams. ReactiveX is a combination of the ...
- Rx响应式编程
RX响应式编程就是异步数据流编程:单击事件或事件总线;(观察者模式) 有一堆的函数能够创建流,也能将任何流-,也能将任何流进行组合和过滤.一个流能够作为另一个流的输入,能够将两个流合并,可以通过过滤流 ...
- RxJava响应式编程,入门的HelloWorld;
RxJava核心就是异步,它也被称之为响应式编程:最大的优势就是随着程序逻辑变得越来越复杂,它依然能够保持简洁. Rxjava真的是让人又爱又恨,因为它的线程切换和链式调用真的很好用,但是入门却有点难 ...
- Rx.NET响应式编程
响应式编程 Rx.NET 了解下 1. 引言 An API for asynchronous programming with observable streams.ReactiveX is a co ...
- 响应式编程库RxJava初探
引子 在读 Hystrix 源码时,发现一些奇特的写法.稍作搜索,知道使用了最新流行的响应式编程库RxJava.那么响应式编程究竟是怎样的呢? 本文对响应式编程及 RxJava 库作一个初步的探索. ...
- iOS开发--Swift RAC响应式编程初探
时间不是很充足, 先少说点, RAC的好处是响应式编程, 不需要自己去设置代理委托, target, 而是主要以信息流(signal), block为主, 看到这里激动吧, 它可以帮你监听你的事件, ...
随机推荐
- springboot打包war包部署到tomcat
1.pom.xml修改处 <modelVersion>4.0.0</modelVersion><groupId>com.xx</groupId>< ...
- [NOIP10.6模拟赛]2.equation题解--DFS序+线段树
题目链接: 咕 闲扯: 终于在集训中敲出正解(虽然与正解不完全相同),开心QAQ 首先比较巧,这题是\(Ebola\)出的一场模拟赛的一道题的树上强化版,当时还口胡出了那题的题解 然而考场上只得了86 ...
- Category VS Extension 原理详解
(一)Category 1.什么是Category? category是Objective-C 2.0之后添加的语言特性,别人口中的分类.类别其实都是指的category.category的主要作用是 ...
- redis系列二: linux下安装redis
下面介绍在Linux环境下,Redis的安装与配置 一. 安装 1.首先上官网下载Redis 压缩包,地址:http://redis.io/download 下载稳定版3.0即可. 2.通过远程管理工 ...
- Java 读取 .properties 文件的几种方式
Java 读取 .properties 配置文件的几种方式 Java 开发中,需要将一些易变的配置参数放置再 XML 配置文件或者 properties 配置文件中.然而 XML 配置文件需要通过 ...
- Oracle笔记(十一) 建表、更新、查询综合练习
有某个学生运动会比赛信息的数据库,保存了如下的表: 运动员sporter(运动员编号sporterid,运动员姓名name,运动员性别sex,所属系号department) 项目item(项目编号it ...
- 玩转springcloud(三):服务的提供者与调用者(注册于发现)
一.简介 上文我们实践了cloud的注册中心的单服务于多节点的搭建,房子造好了得有人来住不是,这篇我们实践下服务提供者于调用者的案例,也就是服务端和客户端的调用. 本文会设计三个module:注册中心 ...
- Ubuntu安装Python 3.6之编译安装+使用PPA源安装
下面分别详细介绍一下Ubuntu 14.04/16.04安装Python 3.6的两种方法: 方法一 自己编译安装: # 安装编译必需的软件包 sudo apt install build-essen ...
- qjson中把记录或类型或泛型数组转换为json字符串
unit Unit4; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...
- TensorFlow 拾遗
1..Here None in placeholder means that a dimension can be of any length. 2.. 3.. 4.. 5.. tf.mul ...