RxJava2与RxJava1的简单对比

前言:

RxJava 2.0已经于2016年10月29日正式发布,本人也专门抽时间研究了一下其相关特性。趁热打铁,在这篇文章里对RxJava2.0的使用进行一个简单的总结。

阅读本文前需要掌握RxJava 1.0的基本概念,如果从未接触过RxJava, 请点击这里

RxJava 2.0 VS RxJava 1.0:

1. RxJava 2.0 不再支持 null 值,如果传入一个null会抛出 NullPointerException;

    Observable.just(null);
    Single.just(null);
    Flowable.just(null);
    Maybe.just(null);
    Observable.fromCallable(() -> null)
            .subscribe(System.out::println, Throwable::printStackTrace);
    Observable.just(1).map(v -> null)
            .subscribe(System.out::println, Throwable::printStackTrace);

2. RxJava 2.0 所有的函数接口(Function/Action/Consumer)均设计为可抛出Exception,解决编译异常需要转换问题;

3. RxJava 1.0 中Observable不能很好支持背压,在RxJava2.0 中将Oberservable彻底实现成不支持背压,而新增Flowable 来支持背压。(关于背压的概念请参考本人对ReativeX的英文原文的中文翻译

 

一. Observable

RxJava 1.0有四个基本概念:Observable(可观察者,即被观察者)、Observer(观察者)、subscribe(订阅)、事件。ObservableObserver通过 subscribe()方法实现订阅关系,从而 Observable可以在需要的时候发出事件来通知 Observer。

            

基于以上的概念, RxJava 1.0的基本实现主要有三点:

step1: 创建 Observer

Observer 即观察者,它决定事件触发的时候将有怎样的行为。 RxJava 中的 Observer 接口的实现方式:

Observer<String> observer = new Observer<String>() {
    @Override
    public void onNext(String s) {
        Log.d(tag, "Item: " + s);
    }

    @Override
    public void onCompleted() {
        Log.d(tag, "Completed!");
    }

    @Override
    public void onError(Throwable e) {
        Log.d(tag, "Error!");
    }
};

除了Observer接口之外,RxJava 还内置了一个实现了Observer的抽象类: SubscriberSubscriberObserver接口进行了一些扩展,但他们的基本使用方式是完全一样的:

Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onNext(String s) {
        Log.d(tag, "Item: " + s);
    }

    @Override
    public void onCompleted() {
        Log.d(tag, "Completed!");
    }

    @Override
    public void onError(Throwable e) {
        Log.d(tag, "Error!");
    }
};

step2:创建 Observable

Observable 即被观察者,它决定什么时候触发事件以及触发怎样的事件。 RxJava 使用 create() 方法来创建一个 Observable ,并为它定义事件触发规则:

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("Hello");
        subscriber.onNext("Hi");
        subscriber.onNext("Aloha");
        subscriber.onCompleted();
    }
});

step3:Subscribe (订阅)

创建了 ObservableObserver之后,再用 subscrbe() 方法将它们联结起来,整条链子就可以工作了。代码形式很简单:

observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);

 

然而,在2.0中我们熟悉的 Subscrber 居然没影了,取而代之的是 ObservableEmitter, 俗称发射器。此外,由于没有了 Subscrber 的踪影,我们创建观察者时需使用 Observer。而 Observer 也不是我们熟悉的那个 Observer,其回调的 Disposable 参数更是让人摸不到头脑。


step1:初始化一个Observable

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

            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
                e.onNext(2);
                e.onComplete();
            }
        });

 

step2:初始化一个Observer


        Observer<Integer> observer= new Observer<Integer>() {

            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Integer value) {


            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
            }
        }

 

step3:建立订阅关系

    observable.subscribe(observer); //建立订阅关系

 

不难看出,与 RxJava1.0 还是存在着一些区别的。首先,创建Observable时,回调的是ObservableEmitter,字面意思即发射器,用于发射数据(onNext())和通知(onError()/onComplete())。其次,创建的Observer中多了一个回调方法 onSubscribe(),传递参数为Disposable

ObservableEmitter: Emitter是发射器的意思,那就很好猜了,这个就是用来发出事件的,它可以发出三种类型的事件,通过调用emitter的 onNext(T value) 、onComplete()和onError(Throwable e)就可以分别发出next事件、complete事件和error事件

Disposable:这个单词的字面意思是一次性用品,用完即可丢弃的。 那么在RxJava中怎么去理解它呢, 对应于上面的水管的例子, 我们可以把它理解成两根管道之间的一个机关, 当调用它的 dispose() 方法时, 它就会将两根管道切断, 从而导致下游收不到事件,即相当于 Subsciption

注意: 调用dispose()并不会导致上游不再继续发送事件, 上游会继续发送剩余的事件.

来看个例子, 我们让上游依次发送 1,2,complete,4,在下游收到第二个事件之后, 切断水管, 看看运行结果:

        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Log.d(TAG, "emit 1");
                emitter.onNext(1);
                Log.d(TAG, "emit 2");
                emitter.onNext(2);
                Log.d(TAG, "emit 3");
                emitter.onNext(3);
                Log.d(TAG, "emit complete");
                emitter.onComplete();
                Log.d(TAG, "emit 4");
                emitter.onNext(4);
            }
        }).subscribe(new Observer<Integer>() {
            private Disposable mDisposable;
            private int i;

            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "subscribe");
                mDisposable = d;
            }

            @Override
            public void onNext(Integer value) {
                Log.d(TAG, "onNext: " + value);
                i++;
                if (i == 2) {
                    Log.d(TAG, "dispose");
                    mDisposable.dispose();
                    Log.d(TAG, "isDisposed : " + mDisposable.isDisposed());
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "error");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "complete");
            }
        });

运行结果为:

12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: subscribe
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 1
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: onNext: 1
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 2
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: onNext: 2
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: dispose
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: isDisposed : true
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 3
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit complete
12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 4

从运行结果我们看到, 在收到onNext 2这个事件后, 切断了水管, 但是上游仍然发送了3, complete, 4这几个事件, 而且上游并没有因为发送了onComplete而停止。 同时可以看到下游的 onSubscibe()方法是最先调用的.

Disposable的用处不止这些, 后面讲解到了线程的调度之后, 我们会发现它的重要性. 随着后续深入的讲解, 我们会在更多的地方发现它的身影.

此外,RxJava2.x中仍然保留了其他简化订阅方法,我们可以根据需求,选择相应的简化订阅。只不过传入的对象改为了 Consumer。`

   Disposable disposable = observable.subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                  //这里接收数据项
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
              //这里接收onError
            }
        }, new Action() {
            @Override
            public void run() throws Exception {
              //这里接收onComplete。
            }
        });

 

不同于RxJava 1.0,RxJava 2.0中没有了一系列的Action/Func接口,取而代之的是与Java8命名类似的函数式接口,如下图: 
image_1arse84b03rfoo89mr1m53151a9.png-30.7kB 
其中Action类似于RxJava 1.0中的Action0,区别在于Action允许抛出异常。

public interface Action {
    /**
     * Runs the action and optionally throws a checked exception
     * @throws Exception if the implementation wishes to throw a checked exception
     */
    void run() throws Exception;
}

 

Consumer即消费者,用于接收单个值, BigConsumer则是接收两个值, Function用于变换对象, Predicate用于判断。这些接口命名大多参照了Java8,熟悉Java8新特性的应该都知道意思,这里也就不再赘述了。

线程调度

关于线程切换这点,RxJava1.x和RxJava2.x的实现思路是一样的。这里就简单看下相关源码。

1. subscribeOn

同RxJava1.x一样, subscribeOn 用于指定 subscribe() 时所发生的线程,从源码角度可以看出,内部线程调度是通过 ObservableSubscribeOn 来实现的。

   public final Observable<T> subscribeOn(Scheduler scheduler) {
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
    }

 

ObservableSubscribeOn 的核心源码在 subscribeActual方法中,通过代理的方式使用SubscribeOnObserver 包装Observer后,设置 Disposable 来将 subscribe 切换到 Scheduler 线程中

    @Override
    public void subscribeActual(final Observer<? super T> s) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);

        s.onSubscribe(parent); //回调Disposable

        parent.setDisposable(scheduler.scheduleDirect(new Runnable() { //设置`Disposable`
            @Override
            public void run() {
                source.subscribe(parent); //使Observable的subscribe发生在Scheduler线程中
            }
        }));
    }

 

2. observeOn

observeOn 方法用于指定下游Observer回调发生的线程。

    public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
         //..
         //验证安全
        return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
    }

 

主要实现在 ObservableObserveOn 中的subscribeActual, 可以看出,不同于subscribeOn, 没有将subscribe 操作全部切换到Scheduler中,而是通过ObserveOnSubscriberScheduler配合,通过schedule()达到切换下游Observer回调发生的线程,这一点与RxJava 1.0实现几乎相同。关于ObserveOnSubscriber 的源码这里不再重复描述了。

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnSubscriber<T>(observer, w, delayError, bufferSize));
        }
    }

 

二. Flowable

Flowable是RxJava 2.0中新增的类,专门用于应对背压(Backpressure)问题,但这并不是RxJava 2.0中新引入的概念。所谓背压,即生产者的速度大于消费者的速度带来的问题,比如在Android中常见的点击事件,点击过快则会造成点击两次的效果。 

我们知道,在RxJava 1.0中背压控制是由Observable完成的,使用如下:

  Observable.range(1,10000)
            .onBackpressureDrop()
            .subscribe(integer -> Log.d("JG",integer.toString()));

而在RxJava 2.0中将其独立了出来,取名为Flowable。因此,原先的Observable已经不具备背压处理能力。 
通过 Flowable, 我们可以自定义背压处理策略。 

/**
 * Represents the options for applying backpressure to a source sequence.
 */
public enum BackpressureStrategy {
    /**
     * OnNext events are written without any buffering or dropping.
     * Downstream has to deal with any overflow.
     * <p>Useful when one applies one of the custom-parameter onBackpressureXXX operators.
     */
    MISSING,
    /**
     * Signals a MissingBackpressureException in case the downstream can't keep up.
     */
    ERROR,
    /**
     * Buffers <em>all</em> onNext values until the downstream consumes it.
     */
    BUFFER,
    /**
     * Drops the most recent onNext value if the downstream can't keep up.
     */
    DROP,
    /**
     * Keeps only the latest onNext value, overwriting any previous value if the
     * downstream can't keep up.
     */
    LATEST
}

测试Flowable例子如下:

  Flowable.create(new FlowableOnSubscribe<Integer>() {

            @Override
            public void subscribe(FlowableEmitter<Integer> e) throws Exception {

                for(int i=0;i<10000;i++){
                    e.onNext(i);
                }
                e.onComplete();
            }
        }, FlowableEmitter.BackpressureStrategy.ERROR) //指定背压处理策略,抛出异常
                .subscribeOn(Schedulers.computation())
                .observeOn(Schedulers.newThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.d("JG", integer.toString());
                        Thread.sleep(1000);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Log.d("JG",throwable.toString());
                    }
                });

 

或者可以使用类似RxJava 1.0的方式来控制。

  Flowable.range(1,10000)
                .onBackpressureDrop()
                .subscribe(integer -> Log.d("JG",integer.toString()));

 

其中还需要注意的一点在于,Flowable并不是订阅就开始发送数据,而是需等到执行Subscription.request()才能开始发送数据。当然,使用简化subscribe订阅方法会默认指定Long.MAX_VALUE。手动指定的例子如下:


        Flowable.range(1,10).subscribe(new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                s.request(Long.MAX_VALUE);//设置请求数
            }

            @Override
            public void onNext(Integer integer) {

            }

            @Override
            public void onError(Throwable t) {

            }

            @Override
            public void onComplete() {

            }
        });

 

三. Single

不同于RxJava 1.0中的 SingleSubscriber,RxJava 2.0中的 SingleObserver多了一个回调方法 onSubscribe

interface SingleObserver<T> {
    void onSubscribe(Disposable d);
    void onSuccess(T value);
    void onError(Throwable error);
}

 

四. Completable

同Single,Completable也被重新设计为Reactive-Streams架构,RxJava 1.0 的 CompletableSubscriber改为 CompletableObserver,源码如下:

interface CompletableObserver<T> {
    void onSubscribe(Disposable d);
    void onComplete();
    void onError(Throwable error);
}

 

五. Subject/Processor

Processor 和 Subject 的作用是相同的。关于Subject部分,RxJava 1.0与RxJava 2.0在用法上没有显著区别,这里就不介绍了。其中Processor是RxJava 2.0新增的,继承自 Flowable, 所以支持背压控制。而Subject则不支持背压控制。使用如下:

    //Subject
    AsyncSubject<String> subject = AsyncSubject.create();
    subject.subscribe(o -> Log.d("JG",o));//three
    subject.onNext("one");
    subject.onNext("two");
    subject.onNext("three");
    subject.onComplete();

    //Processor
    AsyncProcessor<String> processor = AsyncProcessor.create();
    processor.subscribe(o -> Log.d("JG",o)); //three
    processor.onNext("one");
    processor.onNext("two");
    processor.onNext("three");
    processor.onComplete();

 

六. 操作符

关于操作符,RxJava 1.0与RxJava 2.0在命名和行为上大多数保持了一致,需要强调的是subscribeWith操作符和compose操作符。

1. subscribeWith

RxJava 2.0中,subscribe 操作不再返回 Subscription 也就是如今的 Disposable,为了保持向后的兼容, Flowable 提供了subscribeWith方法返回当前的观察者Subscriber对象, 并且同时提供了DefaultSubsriber, ResourceSubscriber, DisposableSubscriber接口,让他们提供 Disposable对象, 从而可以管理其生命周期。

2. compose

RxJava 1.0用法:

	private static <T> Observable.Transformer<T, T> createIOSchedulers() {
		return new Observable.Transformer<T, T>() {
			@Override
			public Observable<T> call(Observable<T> tObservable) {
				return tObservable.subscribeOn(Schedulers.io())
						.unsubscribeOn(AndroidSchedulers.mainThread())
						.observeOn(AndroidSchedulers.mainThread());
			}
		};
	}

	public static <T> Observable.Transformer<JsonResult<T>,T> applySchedulers() {
		return createIOSchedulers();
	}
Action1<Integer> onNext = null;
String[] items = { "item1", "item2", "item3" };
Subscription subscription = Observable.from(items)
                                      .compose(RxUtil.<String>applySchedulers())
                                      .map(new Func1<String, Integer>() {
                                                  @Override public Integer call(String s) {
                                                      return Integer.valueOf(s);
                                                  }
                                              })
                                      .subscribe(onNext);

RxJava 2.0用法:

    public static <T> ObservableTransformer<T, T> io2MainObservable() {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply(Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

	public static <T> ObservableTransformer<T, T> applySchedulers() {
		return io2MainObservable();
	}
Consumer<Integer> onNext = null;
String[] items = { "item1", "item2", "item3" };
Disposable disposable = Observable.fromArray(items)
                                  .compose(RxUtil.<String>applySchedulers())
                                  .map(new Function<String, Integer>() {
                                              @Override public Integer apply(String s) throws Exception {
                                                  return Integer.valueOf(s);
                                              }
                                          })
                                  .subscribe(onNext);

可以注意到,RxJava 1.0中实现的是rx.Observable.Transformer接口, 该接口继承自Func1<Observable<T>, Observable<R>>,  而2.0继承自io.reactivex.ObservableTansformer<Upstream, Downstream>, 是一个独立的接口。

除此之外,RxJava 2.0还提供了 FlowableTransformer接口,用于Flowable下的compose操作符,使用如下:

    public static <T> FlowableTransformer<T, T> io2MainFlowable() {
        return new FlowableTransformer<T, T>() {
            @Override
            public Publisher<T> apply(Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

	public static <T> FlowableTransformer<T, T> applySchedulers() {
		return io2MainFlowable();
	}

Consumer<Integer> onNext = null;
Disposable disposable = Flowable.create(new FlowableOnSubscribe<Integer>() {

            @Override
            public void subscribe(FlowableEmitter<Integer> e) throws Exception {

                for(int i=0;i<10000;i++){
                    e.onNext(i);
                }
                e.onComplete();
            }
        }, FlowableEmitter.BackpressureStrategy.ERROR) //指定背压处理策略,抛出异常
        .compose(RxUtil.<String>applySchedulers())
        .subscribe(onNext);

 

转载于:https://my.oschina.net/u/3389024/blog/883501

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值