RxJava 2.x 学习记录 (一)

172 阅读8分钟

了解 Rxjava, 从其操作符开始

RxJava 的操作符可以划分为下面几类,分别是:

1:创建操作符

create 操作符

create 操作符用于创建被观察者 Observable ,代码如下:
//创建被观察者
Observable observable = Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter emitter) throws Exception {
        emitter.onNext(1+" ");
        emitter.onComplete();
    }
});

//观察者
Observer observer = new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {
        System.out.println("onSubscribe");
    }

    @Override
    public void onNext(String s) {
        System.out.println(s+" ");
    }

    @Override
    public void onError(Throwable e) {
        System.out.println("onError");
    }

    @Override
    public void onComplete() {
        System.out.println("onComplete");
    }
};

//产生订阅关系
observable.subscribe(observer);

如上代码所示,我们使用create 操作符创建了被观察者,并创建了观察者,调用 Observable.subscribe(Observer); 便可产生订阅关系,当产生订阅关系之后,便可以进行事件的传递,这里在 Observer (被观察者) 中发送事件,可传递到 Observer(观察者) 中去,同时我们也发现在 Observer 中含有其他方法,如 onSubscribe() (产生订阅关系的时候会调用), onNext() (在被观察者发送事件的时候会调用), onError() (当出现异常登情况时会调用该方法) , onComplete() (当被观察者调用 emitter.onComplete(); 时会调用 代表事件发送完毕,后面被观察者再发送事件,观察者也接受不到)

下面,我们再来看下上述代码的执行结果:

onSubscribe //产生订阅
1  //发送事件
onComplete //事件发送完毕 

除了 create 操作符外,还有其他创建操作符:

just 创建操作符

just 操作符可以说是简化的 create 操作符,eg:

Observable observable = Observable.just("12345");
Observer observer = new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(String s) {
        System.out.println(s);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
};
observable.subscribe(observer);
如上,直接创建了 Observable 和 Observer ,这样写法会较之前而言简化一些。但得到的结果是一样的。
然后,其实我们还可以再接着简化:
Observable.just("12345").subscribe(new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(String s) {
        System.out.println(s);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});
再接着简化:
Observable.just("12345").subscribe(new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        System.out.println(s);
    }
});
如上三种写法,得到的结果均是相同的。

fromArray 创建操作符

fromArray 操作符适用于发射的数据是一个数组的情况,类似一个遍历数组的功能,eg:

Observable.fromArray(new Integer[]{1,2,3,4,5}) //创建 observable
        .subscribe(new Observer<Integer>() {//创建 observer 并产生订阅
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Integer integer) {
                System.out.println(integer);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
得到的结果如下:
1
2
3
4
5
从如上 log 中可以看到,在事件上游往下游传递过程中,遍历了数组的每一个元素,并单独发送事件。

empty 创建操作符

empty 创建操作符用于创建一个空事件的被观察者,eg:

Observable.empty().subscribe(new Observer<Object>() {
    @Override
    public void onSubscribe(Disposable d) {
        System.out.println("onSubscribe()");
    }

    @Override
    public void onNext(Object o) {
        System.out.println("onNext()");
    }

    @Override
    public void onError(Throwable e) {
        System.out.println("onError");
    }

    @Override
    public void onComplete() {
        System.out.println("onComplete()");
    }
});
打印 log 如下:
onSubscribe() //创建订阅
onComplete() //完成事件发送

注:由于 empty 操作符为创建一个空事件的操作符,所以不会调用 onNext() 方法。

如上为平常用得稍微频繁些的操作符,还有一些其他操作符,如 defer , timer , interval 等也属于创建操作符,与上述操不多,这里不再赘述,有用到时可以查看官方文档中的操作符列表

2:转换操作符

转换操作符,是在从 Observable 发射事件到 Observer 的途中,将发送的事件进行一系列操作的操作符。下面来具体看下一部分常用的转换操作符:

map 转换操作符,下面看图说话,直接上代码,eg:

//创建被观察者
Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
        emitter.onNext(2);
        emitter.onNext(4);
        emitter.onNext(7);
        emitter.onComplete();
    }
}).map(new Function<Integer, String>() { //使用 map 操作符进行变换,将传递的integer转换成了String
    @Override
    public String apply(Integer integer) throws Exception {
        return "apply:" + integer;
    }
}).subscribe(new Observer<String>() {

    @Override
    public void onSubscribe(Disposable d) {
        
    }

    @Override
    public void onNext(String s) {
        //打印 log
        System.out.println(s);
    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});

得到的 log 如下:

apply:2
apply:4
apply:7

从结果中不难得出,我们在 Observer 中的到的事件 已经是经过了 map 处理后的 事件数据了。

此类转换可以用于加载图片等操作,伪代码可如下进行操作:

Observable.just("header.png")//发射图片 url
        .map(new Function<String, Bitmap>() {
            @Override
            public Bitmap apply(String s) throws Exception {
                return loadImage(s);//通过 s 这个图片 url 加载图片
            }
        })
        .subscribeOn(Schedulers.io()) //耗时操作在子线程中执行
        .observeOn(AndroidSchedulers.mainThread()). //调度到主线程显示
        subscribe(new Consumer<Bitmap>() {
    @Override
    public void accept(Bitmap bitmap) throws Exception {
        showBitmap();
    }
});

flatmap 变换操作符:

flatMap 是一个很有趣的东西,我坚信你在实际开发中会经常用到。它可以把一个发射器 Observable 通过某种方法转换为多个 Observables,然后再把这些分散的 Observables装进一个单一的发射器 Observable。但有个需要注意的是,flatMap 并不能保证事件的顺序,如果需要保证,需要用到我们下面要讲的 ConcatMap。eg:

public void testFlatmap(){
    Observable.just("getConfig","login")
            .flatMap(new Function<String, ObservableSource<String>>() {
                @Override
                public ObservableSource<String> apply(String s) throws Exception {
                    return createResponse(s);
                }
            }).subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(String s) {
            System.out.println("onNext--->"+s);
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    });
}

public Observable<String> createResponse(final String s){
    return Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            emitter.onNext("login----->"+s);
        }
    });
}
得到的 log 如下:
onNext--->login----->getConfig
onNext--->login----->login

groupBy 分组操作符:

groupBy 操作符 是将事件通过一定的逻辑分成组别,eg:

Observable.just(2,5,1,7,4,9)
        .groupBy(new Function<Integer, Boolean>() {
            @Override
            public Boolean apply(Integer integer) throws Exception {
                return integer > 5? true : false;
            }
        }).subscribe(new Consumer<GroupedObservable<Boolean, Integer>>() {
    @Override
    public void accept(GroupedObservable<Boolean, Integer> booleanIntegerGroupedObservable) throws Exception {
        //打印组别
        System.out.println(booleanIntegerGroupedObservable.getKey());
    }
});
得到的 log 如下:
false
true

上面我们是打印了归类后的组别,下面再来打印下具体的每个组别中的数据:

Observable.just(2,5,1,7,4,9)
        .groupBy(new Function<Integer, Boolean>() {
            @Override
            public Boolean apply(Integer integer) throws Exception {
                return integer > 5? true : false;
            }
        }).subscribe(new Consumer<GroupedObservable<Boolean, Integer>>() {
    @Override
    public void accept(final GroupedObservable<Boolean, Integer> booleanIntegerGroupedObservable) throws Exception {
        //打印组别
        //System.out.println(booleanIntegerGroupedObservable.getKey());
        //遍历打印 具体组别的数据
        booleanIntegerGroupedObservable.subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                //获取到组的key
                boolean key = booleanIntegerGroupedObservable.getKey();
                //组装打印
                System.out.println("key:"+ key + "vaule:" + integer);
            }
        });
    }
});
得到的 log 如下:
key:false  vaule:2
key:false  vaule:5
key:false  vaule:1
key:true  vaule:7
key:false  vaule:4
key:true  vaule:9
可以看到,在我们的判断条件下(value > 5-->true)

buffer 分组操作符

buffer 是将一组数据分为多组数据,函数有多个重载,可以了解一下,skip 代表步长,count 代表每一组的数据个数,eg:

Observable.fromArray(new Integer[]{1,2,3,4,5,6,7,8,9})
        .buffer(3)
//                .buffer(3,2)
        .subscribe(new Consumer<List<Integer>>() {
            @Override
            public void accept(List<Integer> integers) throws Exception {
                System.out.println(integers);
            }
        });
得到的 log 如下:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
从上述 log 可以清晰看到,被分为了多组且每组至多为 count 个数据。

使用场景:

10000条数据插入到数据库中时 每一条数据产生都需要时间
如果产生一条 插入一条比较浪给时间,全部一次性插入用户等的太久
采取buffer的形式 将10000条 分成 一小段执行

reduce 操作符

reduce 是将数据进行处理后合并成一个总的数据,发射给观察者,eg:
Observable.just(2,3,4,5,6,7)
        .reduce(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 integer) throws Exception {
        System.out.println(integer);
    }
});
得到的 log 如下:
27//只有最终结果

再来看下 scan 操作符,eg:

Observable.just(1,2,3,4,5,6)
        .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 integer) throws Exception {
        System.out.println(integer);
    }
});
得到的结果如下:
1
3
6
10
15
21

scan 与 reduce 的 功能都是相同的,不同指出在于:scan 同时关注过程和结果,而 reduce 只关注结果。

window 操作符:

window 按照实际划分窗口,将数据发送给不同的 Observable

Observable.interval(1,TimeUnit.SECONDS)
        .take(15)
        .window(3,TimeUnit.SECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<Observable<Long>>() {
            @Override
            public void accept(Observable<Long> longObservable) throws Exception {
                longObservable.subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        System.out.println("onSubscribe");
                    }

                    @Override
                    public void onNext(Long aLong) {
                        System.out.println(aLong);
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("onError");
                    }

                    @Override
                    public void onComplete() {
                        System.out.println("onComplete");
                    }
                });
        }
        });

得到的 log 如下:

19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 0
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 1
     *  19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
     *  19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 2
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 3
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 4
     *  19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
     *  19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
     *  19232-19232/com.example.justh.rxjavatrain I/System.out: 5
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 6
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 7
     *  19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
     *  19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
     *  119232-19232/com.example.justh.rxjavatrain I/System.out: 8
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 9
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 10
     *  19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
     *  19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 11
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 12
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 13
     *  19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
     *  19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: 14
     *  19232-19750/com.example.justh.rxjavatrain I/System.out: onComplet

到这里,常用的变换操作符就差不许多了,其余的可以参考官方文档上的相关叙述

3:过滤操作符

4:条件操作符

5:合并操作符