Rxjava2 Observable的数据变换详解及实例(一)

本文详细解释了RxJava2中用于数据变换的方法,包括Buffer的各种用法如按数量、边界、时间和间隔收集数据,Map的映射操作,FlatMap、FlatMapIterable的合并与转换,ConcatMap的有序链接,以及SwitchMap的选择订阅。通过实例展示了如何在实际开发中运用这些操作符进行数据处理。
摘要由CSDN通过智能技术生成

简要:

需求了解:

对于 Observable 发射的数据有的时候可能不满足我们的要求,或者需要转化为其他类型的数据,比如:缓存,数据类型转化,数据拦截等。此时可以使用 Rx 中的一些对于数据操作的操作进行数据的变换,方便我们的开发。

执行变换的操作方法:

  • Buffer:它定期从Observable收集数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个
  • Map:对序列的每一项都应用一个函数来变换Observable发射的数据序列
  • FlatMap,FlatMapIterable,ConcatMap:将Observable发射的数据集合变换为Observables集合,然后将这些Observable发射的数据平铺化的放进一个单独的 Observable
  • SwitchMap:将Observable发射的数据集合变换为Observables集合,然后只发射这些Observables最近发射的数据
  • Window:定期将来自Observable的数据分拆成一些Observable窗口,然后发射这些窗口,而不是每次发射一项
  • GroupBy:将Observable分拆为Observable集合,将原始Observable发射的数据按 Key
    分组,每一个Observable发射一组不同的数据
  • Scan:对Observable发射的每一项数据应用一个函数,然后按顺序依次发射每一个值
  • Cast:在发射之前强制将Observable发射的所有数据转换为指定类型

1. Buffer

定期收集Observable的数据放进一个数据包裹(缓存),然后发射这些数据包裹,而不是一次发射一个值。

img-buffer

Buffer 操作符将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生 的Observable发射这些数据的缓存集合。 Buffer 操作符在很多语言特定的实现中有很多种变 体,它们在如何缓存这个问题上存在区别。

Window 操作符与 Buffer 类似,但是它在发射之前把收集到的数据放进单独的Observable, 而不是放进一个数据结构。

注意: 如果原来的Observable发射了一个 onError 通知, Buffer 会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable发射的数据。

在RxJava中的一些 Buffer 的操作如下:

1.1 buffer(count)

img-buffer(count)

以列表(List)的形式发射非重叠的缓存,每一个缓存至多包含来自原始 Observable 的 count 项数据(最后发射的列表数据可能少于count项)。

实例代码:

	// 1. buffer(count) 	
	// 以列表(List)的形式发射非重叠的缓存,
	// 每一个缓存至多包含来自原始 Observable的count项数据(最后发射的列表数据可能少于count项)
	Observable.range(1, 10)
		.buffer(3)
		.subscribe(new Consumer<List<Integer>>() {
   

			@Override
			public void accept(List<Integer> t) throws Exception {
   
				System.out.println("--> bufferr(1) accept: " + t);
			}
		});

输出:

--> bufferr(1) accept: [1, 2, 3]
--> bufferr(1) accept: [4, 5, 6]
--> bufferr(1) accept: [7, 8, 9]
--> bufferr(1) accept: [10]

Javadoc: buffer(count)

1.2 buffer(boundary)

开始创建一个List 收集原始 Observable 数据,监视一个名叫 boundary 的Observable,每当这个Observable发射了一个值,它就创建一个新的 List 开始收集来自原始Observable的数据并发射原来已经收集数据的 List, 当 boundary Observable 发送了完成通知,会将此时还未发送的 List 发送。

注意: 所有发送的 List 可能没有收集到数据,此时数据的收集可能并不会完整收集所有原始 Observable 数据。

img-buffer(boundary)

实例代码:

	// 2. buffer(boundary) 监视一个名叫boundary的Observable,
	// 开始创建一个List收集原始 Observable 数据,监视一个名叫boundary的Observable,
	// 每当这个Observable发射了一个值,它就创建一个新的List开始收集来自原始Observable的数据并发射原来已经收集数据的List,
	// 当boundary发送了完成通知,会将此时还未发送的 List 发送。 
	// 所有发送的 List 可能没有收集到数据,此时数据的收集可能并不会完整收集所有原始Observable数据。
	Observable.range(1, 10000)
		.buffer(Observable.timer(1, TimeUnit.MILLISECONDS)) 		// 1毫秒后开始接受原始数据
		.subscribe(new Consumer<List<Integer>>() {
   

			@Override
			public void accept(List<Integer> t) throws Exception {
   
				System.out.println("--> accept(2): " + t.size());	// 每次收集的数据序列个数
			}
		});

输出:

--> accept(2): 2858
--> accept(2): 5471

Javadoc: buffer(boundary)

1.3 buffer(count, skip)

从原始Observable的第一项数据开始创建新的缓存,此后每当收 到 skip 项数据,用 count 项数据填充缓存:开头的一项和后续的 count-1 项,它以列表 (List)的形式发射缓存,取决于 count 和 skip 的值,这些缓存可能会有重叠部分(比如skip < count时),也可能会有间隙(比如skip > count时)。

img-buffer(count, skip)

解析: 在指定的数据序列中移动指针来获取缓存数据:指针每次移动 skip 个数据长度,每次缓存指针位置及后面count个数据,指针初始位置在原始数据的第一个(存在的情况下)。

实例代码:

	// 3. buffer(int count, int skip)
	// 在指定的数据中移动指针来获取缓存数据:指针每次移动1个数据长度,每次缓存3个数据
	Observable.range(1, 5)
		.buffer(3, 1)
		.subscribe(new Consumer<List<Integer>>() {
   

			@Override
			public void accept(List<Integer> t) throws Exception {
   
				System.out.println("--> bufferr(3) accept: " + t);
			}
		});

输出:

--> bufferr(3) accept: [1, 2, 3]
--> bufferr(3) accept: [2, 3, 4]
--> bufferr(3) accept: [3, 4, 5]
--> bufferr(3) accept: [4, 5]
--> bufferr(3) accept: [5]

Javadoc: buffer(count, skip)

1.4 buffer(timespan, TimeUnit)

定期以 List 的形式发射新的数据,在每个时间段,收集来自原始 Observable 的数据(从前面一个数据包裹之后,或者如果是第一个数据包裹,从有观察者订阅原来的 Observale 之后开始)。还有另一个版本的 buffer 接受一个 Scheduler 参数。

img-buffer(timespan,TimeUnit)
解析: 每隔 timespan 时间段以 List 的形式收集原始Observable的数据

实例代码:

	// 4. buffer(long timespan, TimeUnit unit)
	// 每隔timespan时间段以list的形式收集数据
	Observable.range(1, 50000)
		.buffer(1, TimeUnit.MILLISECONDS)									// 每隔1毫秒收集一次原始序列数据
		.subscribe(new Consumer<List<Integer>>() {
   

			@Override
			public void accept(List<Integer> t) throws Exception {
   
				System.out.println("--> bufferr(4) accept: " + t.size());	// 每次收集的数据序列个数
			}
		});

输出:

--> bufferr(4) accept: 2571
--> bufferr(4) accept: 5457
--> bufferr(4) accept: 13248
--> bufferr(4) accept: 12755
--> bufferr(4) accept: 9543
--> bufferr(4) accept: 6426

注意: buffer(timespan,TimeUnit) 默认情况下会使用 computation 调度器
Javadoc: buffer(timespan,TimeUnit)
Javadoc: buffer(timespan,TimeUnit,Scheduler)

1.5 buffer(timespan, TimeUnit, count)

每当收到来自原始 Observablecount 项数据,或者每过了一段指定 timespan 时间后, 就以 List 的形式发射这期间的数据,即使数据项少于 count 项。还有另一个版本的 buffer 接受一个 Scheduler 参数。

img-buffer(timespan, TimeUnit, count)

实例代码:

	// 5. buffer(long timespan, TimeUnit unit, int count)
	// 每隔1毫秒缓存50个数据
	Observable.range(1, 1000)
		.buffer(1, TimeUnit.MILLISECONDS, 50)								// 每隔1毫秒收集50个数据序列
		.subscribe(new Consumer<List<Integer>>() {
   

			@Override
			public void accept(List<Integer> t) throws Exception {
   
				System.out.println("--> bufferr(5) accept: " + t.size());	// 每次收集的数据序列个数
			}
		});

输出:

--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 20
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 4
--> bufferr(5) accept: 50
--> buf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值