RxJava 响应式编程初探

前言

最近在学习Spring Cloud Hystrix框架,发现里面的代码写法跟传统的编程思路很不一样,充满了回调和Lamda风格,于是去深入了解了一下,这便是本文的主题 RxJava 响应式编程。

RxJava

我们一般写的程序,以流程为核心的,每一行代码实际上都是机器实际上要执行的指令,称之为命令式程序。而RxJava这样的编程风格,称为函数响应式编程函数响应式编程是以数据流为核心,处理数据的输入,处理以及输出的,这种思路写出来的代码就会跟机器实际执行的指令大相径庭。既然涉及到响应,便会想到观察者模式,的确,RxJava 是基于Java观察者设计模式的。

RxJava 最核心的两个东西是Observable(被观察者,事件源)和Subscriber(观察者)。Observable 发出一系列事件,Subscriber 处理这些事件。

一个 Observable 可以发出零个或者多个事件,知道结束或者出错。每发出一个事件,就会调用它的Subscriber的onNext方法,最后调用Subscriber.onNext()或者Subscriber.onError()结束。

这里跟观察者模式有一点明显不同,那就是如果一个 Observable 没有任何的 Subscriber,那么这个 Observable 是不会发出任何事件的。

基本用法

        Observable<String> myObservable = Observable.create(new Observable.OnSubscribe<String>() {
            public void call(Subscriber<? super String> subscriber) {
                System.out.println("====Hello World!====");
                subscriber.onNext("Hello World!");
                subscriber.onCompleted();
            }
        });

上述代码中我们创建了一个 Observable 对象,当 Observable 被订阅的时候,OnSubscribe 的 call() 方法会自动被调用,事件序列就会依照设定依次触发(上述代码中,观察者 Subscriber 将会被调用一次 onNext() 和一次 onCompleted())。被观察者调用了观察者的回调方法,就实现了由被观察者向观察者的事件传递,即观察者模式。

        Subscriber<String> mySubscriber = new Subscriber<String>() {
            public void onCompleted() {

            }

            public void onError(Throwable throwable) {

            }

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

上文中提到,只有 Observable 对象而没有 Subscriber 对象,那么这个 Observable 是不会发出任何事件的。上述代码中,我们创建了一个 Subscriber 对象,并且重写了 onNext()、onError()、onCompleted() 三个方法。

        myObservable.subscribe(mySubscriber);

通过 subscribe 方法将 myObservable 对象和 mySubscriber 对象关联起来,这样就完成了subscriber对observable的订阅。

Observable 简化用法

上述代码仅仅为了打印一个“hello world”难免让人觉得啰嗦,RxJava 其实提供了很多便捷的函数来帮助我们减少代码。

  • 使用just( ),将为你创建一个 Observable 并自动为你调用 onNext( ) 发射数据:
        Observable.just("Hello World!").subscribe(mySubscriber);
  • 使用from( ),遍历集合,发送每个item:
        List<String> list = new ArrayList<String>();
        list.add("Hello");
        list.add("World!");
        Observable.from(list).subscribe(mySubscriber);
  • 使用defer( ),有观察者订阅时才创建Observable,并且为每个观察者创建一个新的Observable:
        Observable<String> myObservable = Observable.defer(new Func0<Observable<String>>() {
            public Observable<String> call() {
                return Observable.just("Hello","World!");
            }
        });

Subscriber 简化用法

大部分时候我们并不关心 OnComplete 和 OnError,我们只需要在 onNext 的时候做一些处理,这时候就可以使用Action1类。

        Action1<String> onNextAction = new Action1<String>() {
            @Override
            public void call(String s) {
                System.out.println(s);
            }
        };

        Observable.just("Hello","World!").subscribe(onNextAction);

RxJava 高级部分

map 操作符

map 操作符就是用于变换Observable对象的,把一个事件转换为另一个事件,map操作符返回一个Observable对象,这样就可以实现链式调用,在一个Observable对象上多次使用map操作符,最终将最简洁的数据传递给Subscriber对象。

        Observable.just("1+2").map(new Func1<String, Integer>() {
            public Integer call(String str){
                String[] strs = str.split("\\+");
                return Integer.valueOf(strs[0])+Integer.valueOf(strs[1]);
            }
        }).subscribe(new Action1<Integer>() {
            public void call(Integer integer) {
                System.out.print(integer);
            }
        });

上述代码将一个代表数值表达式的字符串转换为最后的计算结果并输出。

线程控制(Scheduler)

使用 RxJava,你可以使用 subscribeOn() 指定观察者代码运行的线程,使用 observerOn() 指定订阅者运行的线程

RxJava 已经内置了几个 Scheduler ,它们已经适合大多数的使用场景:

  • Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。

  • Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。

  • Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。

  • Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。

有了以上这几个 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制了。

  • subscribeOn(): 指定 subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。

  • observeOn(): 指定 Subscriber 所运行在的线程。或者叫做事件消费的线程。

    observable
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(subscribe);

总结

本文大致介绍了RxJava的一些基本用法,真正的RxJava绝不是这么三言两语能够说清的,需要用户在实际使用过程中去理解它。

猜你喜欢

转载自blog.csdn.net/tjreal/article/details/80215655