5、Rxjava-变换操作符

454 阅读6分钟

作用

对事件序列中的事件 / 整个事件序列 进行加工处理(即变换),使得其转变成不同的事件 / 整个事件序列

类型

类型 作用
Map() 对序列的每一项都用一个函数来变换 Observable 发射的数据序列
scan() 与Map()类似,但是它有两个参数
FlatMap() 生成新的 Observable,无序
ConcatMap() 生成新的 Observable,有序
Buffer() 指定数量到缓冲区发送
window() 定期将来自 Observable 的数据拆分成一些 Observable 窗口,然后发射这些窗口,而不是每次发射一项
groupBy() 将 Observable 拆分为 Observable 集合,将原始 Observable 发射的数据按 Key 分组,每一个 Observable 发射过一组不同的数据
cast() 在发射之前强制将 Observable 发射的所有数据转换为指定class对象

Map():事件转换(一个参数)

对 Observable 发送的每一个事件都通过 指定的函数(一个参数) 处理,从而变换成另外一种事件

将被观察者发送的事件转换为任意的类型事件

Observable.create(new ObservableOnSubscribe<Integer>() {

    // 1. 被观察者发送事件 = 参数为整型 = 1、2、3
    @Override
    public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
        emitter.onNext(1);
        emitter.onNext(2);
        emitter.onNext(3);

    }
    // 2. 使用Map变换操作符中的Function函数对被观察者发送的事件进行统一变换:整型变换成字符串类型
}).map(new Function<Integer, String>() {
    @Override
    public String apply(Integer integer) throws Exception {
        return "使用 Map变换操作符 将事件" + integer +"的参数从 整型"+integer + " 变换成 字符串类型" + integer ;
    }
}).subscribe(new Consumer<String>() {

    // 3. 观察者接收事件时,是接收到变换后的事件 = 字符串类型
    @Override
    public void accept(String s) throws Exception {
        Log.d(TAG, s);
    }
});

>>>>>>
使用 Map变换操作符 将事件1的参数从 整型1变换成 字符串类型1
使用 Map变换操作符 将事件2的参数从 整型2变换成 字符串类型2
使用 Map变换操作符 将事件3的参数从 整型3变换成 字符串类型3

scan():事件转换(两个参数)

对 Observable 发送的每一个事件都通过 指定的函数(两个参数) 处理,从而变换成另外一种事件

Observable.create(new ObservableOnSubscribe<Integer>() {

    @Override
    public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
        emitter.onNext(10);
        emitter.onNext(20);
        emitter.onNext(30);
    }
}).scan(new BiFunction<Integer, Integer, Integer>() {
    @Override
    public Integer apply(Integer integer, Integer integer2) throws Exception {
        return integer * integer2;
    }
}).subscribe(new Consumer<Integer>() {

    @Override
    public void accept(Integer s) throws Exception {
        // 发射10的时候,value为10
        // 发射20的时候,用保存的value 10运算得到200
        // 发射30的时候,用保存的value 200运算得到6000
        Log.d(TAG, "聚合值=" + s);
    }
});

>>>>>>
聚合值=10
聚合值=200
聚合值=6000

FlatMap():生成新的 Observable,无序

将被观察者发送的事件序列进行 拆分 & 单独转换,再合并成一个新的事件序列,最后再进行发送

  1. 为事件序列中每个事件都创建一个 Observable 对象;
  2. 将对每个 原始事件 转换后的 新事件 都放入到对应 Observable对象;
  3. 将新建的每个Observable 都合并到一个 新建的、总的Observable 对象;
  4. 新建的、总的Observable 对象 将 新合并的事件序列 发送给观察者(Observer)
Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
        emitter.onNext(1);
        emitter.onNext(2);
        emitter.onNext(3);
    }

    // 采用flatMap()变换操作符
}).flatMap(new Function<Integer, ObservableSource<String>>() {
    @Override
    public ObservableSource<String> apply(Integer integer) throws Exception {
        final List<String> list = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            list.add("我是事件 " + integer + "拆分后的子事件" + i);
            // 通过flatMap中将被观察者生产的事件序列先进行拆分,再将每个事件转换为一个新的发送三个String事件
            // 最终合并,再发送给被观察者
        }
        return Observable.fromIterable(list);
    }
}).subscribe(new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        Log.d(TAG, s);
    }
});

>>>>>>
我是事件 3拆分后的子事件0
我是事件 2拆分后的子事件0
我是事件 2拆分后的子事件1
我是事件 1拆分后的子事件0
我是事件 1拆分后的子事件1
我是事件 1拆分后的子事件2
我是事件 3拆分后的子事件1
我是事件 3拆分后的子事件2
我是事件 2拆分后的子事件2

注:新合并生成的事件序列顺序是无序的,即 与旧序列发送事件的顺序无关

ConcatMap():生成新的 Observable,有序

FlatMap() 作用相同

注:新合并生成的事件序列顺序是有序的,即 严格按照旧序列发送事件的顺序

Buffer():分组发射,发射的是事件

定期从 被观察者(Observable)需要发送的事件中 获取一定数量的事件 & 放到缓存区中,最终发送

// 被观察者 需要发送5个数字
Observable.just(1, 2, 3, 4, 5)
        .buffer(3, 1) // 设置缓存区大小 & 步长
                            // 缓存区大小 = 每次从被观察者中获取的事件数量
                            // 步长 = 每次获取新事件的数量
        .subscribe(new Observer<List<Integer>>() {
            @Override
            public void onSubscribe(Disposable d) {

            }
            @Override
            public void onNext(List<Integer> stringList) {
                //
                Log.d(TAG, " 缓存区里的事件数量 = " +  stringList.size());
                for (Integer value : stringList) {
                    Log.d(TAG, " 事件 = " + value);
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "对Error事件作出响应" );
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "对Complete事件作出响应");
            }
        });

>>>>>>
缓存区里的事件数量 = 3
事件 = 1
事件 = 2
事件 = 3
缓存区里的事件数量 = 3
事件 = 2
事件 = 3
事件 = 4
缓存区里的事件数量 = 3
事件 = 3
事件 = 4
事件 = 5
缓存区里的事件数量 = 2
事件 = 4
事件 = 5
缓存区里的事件数量 = 1
事件 = 5
对Complete事件作出响应


说明:
设置缓存区大小为3,则第一次获取3个事件存在缓冲区发射,即事件123
第二次因为步长设置为1,所以会获取1个新的事件,即指针继续往后移1个,事件234
...
最后指针本来要3个事件但后移没有事件了,所以只能发射事件5

window():分组发射,发射的是Observable

定期将来自 Observable 的数据拆分成一些 Observable 窗口,然后发射这些窗口,而不是每次发射一项

Observable.range(1, 7)
        .window(2)
        .subscribe(new Consumer<Observable<Integer>>() {
            @Override
            public void accept(Observable<Integer> integerObservable) throws Exception {
                Log.d(TAG, "onNext");
                integerObservable.subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.d(TAG, "accept:" + integer);
                    }
                });
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                Log.d(TAG, "onError");
            }
        }, new Action() {
            @Override
            public void run() throws Exception {
                Log.d(TAG, "onComplete");
            }
        });
        
>>>>>>
onNext
accept:1
accept:2
onNext
accept:3
accept:4
onNext
accept:5
accept:6
onNext
accept:7
onComplete

groupBy():分组

将一个 Observable 拆分为一些 Observables 集合,它们中的每一个都发射原始 Observable 的一个子序列

Observable.range(1, 8)
        .groupBy(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return (integer % 2 == 0) ? "偶数" : "奇数";
            }
        }).subscribe(new Consumer<GroupedObservable<String, Integer>>() {
    @Override
    public void accept(GroupedObservable<String, Integer> stringIntegerGroupedObservable) throws Exception {
        final String key = stringIntegerGroupedObservable.getKey();
        stringIntegerGroupedObservable.subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d(TAG, key + "包含:" + integer);
            }
        });

    }
});

>>>>>>
奇数包含:1
偶数包含:2
奇数包含:3
偶数包含:4
奇数包含:5
偶数包含:6
奇数包含:7
偶数包含:8