RxJava2 vs RxJava1

官方WIKI What's different in 2.0

RxJava2已经发布了两周了,相比RxJava1,它的改动还是很大的:


Observable and Flowable

在前一个版本里backpressure被集成到了Observable中,官方也提供了很多方法让我们来处理backpressure问题。但是有一些特殊的场景根本无法用其来解决,最常见的例如UI事件。而不处理backpressure有可能导致MissingBackpressureException的出现。

关于backpressure的概念可以看一下RxJava中backpressure这个概念的理解

为了解决这个问题,在RxJava2里,引入了Flowable这个类:Observable不包含backpressure处理,而Flowable包含。

例如:

Flowable<Long> flowable = 
    Flowable.create((FlowableOnSubscribe<Long>) e -> {
        Observable.interval(10, TimeUnit.MILLISECONDS)
            .take(Integer.MAX_VALUE)
            .subscribe(e::onNext);
}, FlowableEmitter.BackpressureMode.DROP);


Observable<Long> observable = 
    Observable.create((ObservableOnSubscribe<Long>) e -> {
        Observable.interval(10, TimeUnit.MILLISECONDS)
            .take(Integer.MAX_VALUE)
            .subscribe(e::onNext);
});

两个对象都以10毫秒一次派发数据,假设订阅他们的方法都是:

i -> {
    Thread.sleep(100);
    Log.v("TEST", "out : " + i);
}

以100毫秒一次消费数据,消费数据的效率是生产的1/10。那么

  • 对于observable
    他会按照0,1,2,3,4...的顺序依次消费,并输出log,而没有消费的数据将会都存在内存中。如果在RxJava1中,内存数据超过128个时将会抛出MissingBackpressureException错误;而在RxJava2中并不会报错,数据会一直放到内存中,直到发生OutOfMemoryError

  • 对于flowable, 在创建时我们设定了FlowableEmitter.BackpressureMode.DROP,一开始他会输出0,1,2,3....127但之后会忽然跳跃到966,967,968 ...。中间的部分数据由于缓存不了,被抛弃掉了。


Single

和Observable,Flowable一样会发送数据,不同的是订阅后只能接受到一次:

Single<Long> single = Single.just(1l);

single.subscribe(new SingleObserver<Long>() {
    @Override
    public void onSubscribe(Disposable d) {
    }

    @Override
    public void onSuccess(Long value) {
        // 和onNext是一样的
    }

    @Override
    public void onError(Throwable e) {
    }
});

普通Observable可以使用toSingle转换:Observable.just(1).toSingle()


Completable

与Single类似,只能接受到完成(onComplete)和错误(onError)

同样也可以由普通的Observable转换而来:Observable.just(1).toCompletable()


Base reactive interfaces

和Flowable的接口Publisher类似,Observable、Single、Completable也有类似的基类

interface ObservableSource<T> {
    void subscribe(Observer<? super T> observer);
}

interface SingleSource<T> {
    void subscribe(SingleObserver<? super T> observer);
}

interface CompletableSource {
    void subscribe(CompletableObserver observer);
}

因此许多操作符接受的参数从以前的具体对象,变成了现在的接口:

Flowable<R> flatMap(
    Function<? super T, ? extends Publisher<? extends R>> mapper
);

Observable<R> flatMap(
    Function<? super T, ? extends ObservableSource<? extends R>> mapper
);

------
// 以前
Observable<R> flatMap(Func1<? super T, ? extends Observable<? extends R>> func) {

由于接收的都是接口,在使用其他遵循Reactive-Streams设计的第三方库的时候,就不需要把他自定义的Flowable转换成标准Flowable了。


Subjects and Processors

io.reactivex.subjects.AsyncSubject,
io.reactivex.subjects.BehaviorSubject,
io.reactivex.subjects.PublishSubject,
io.reactivex.subjects.ReplaySubject,
io.reactivex.subjects.UnicastSubject

在RxJava2中依然存在,但现在他们不支持backpressure。新出现的

io.reactivex.processors.AsyncProcessor,
io.reactivex.processors.BehaviorProcessor,
io.reactivex.processors.PublishProcessor,
io.reactivex.processors.ReplayProcessor
io.reactivex.processors.UnicastProcessor

支持backpressure


Other classes

rx.observables.ConnectableObservable变成了io.reactivex.observables.ConnectableObservable<T>io.reactivex.flowables.ConnectableFlowable<T>

类似的还有rx.observables.GroupedObservable


Functional interfaces

需要注意的一点是,现在RxJava2的接口方法里加上了throws Exception:

ublic interface Consumer<T> {
    void accept(T t) throws Exception;
}

意味着在这些方法里调用一些会发生异常的方法不需要try-catch


Actions

另外大部分接口方法都按照Java8的接口方法名进行了相应的修改,比如上面那个Consumer<T>接口原来叫Action1<T>,而Action2<T>改名成了BiConsumer

Action3-Action9被删掉了,大概因为没人用。。


Functions

同上,基本就是名字的修改和不常用类的删除


Subscriber

RxJava1里Subscriber只是一个空接口,在新版里Subscriber被赋予了更多的作用,有几个实现类可以供我们使用,例如

ResourceSubscriber<Integer> subscriber = new ResourceSubscriber<Integer>() {
    @Override
    public void onStart() {
        request(Long.MAX_VALUE);
    }

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

    @Override
    public void onError(Throwable t) {
        t.printStackTrace();
    }

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

request()方法可以控制当前subscriber需要接收几个事件。而且,还可以调用subscriber.dispose()来断开对信号的监听。

同时,onCompleted方法改成了onComplete。意味着完成时调用这个方法,而不是完成后d

由于Subscription被改掉了(下面会讲到)。如果需要类似以前CompositeSubscription的用法,可以使用:

CompositeDisposable composite2 = new CompositeDisposable();
composite2.add(Flowable.range(1, 5).subscribeWith(subscriber));

注意这里需要使用subscribeWith而不是subscribe,因为subscribe方法现在返回void


Subscription

在RxJava1里,Subscription起到的是订阅桥梁的作用。在2中,由于Subscription本身和Reactive-Streams里的另外一个同名概念冲突。因此把原本的Subscription改名成了Disposable

除了上一节里subscribe(Subscriber )方法返回void,其他名为subscribe的方法都返回Disposable

相应的,

  • CompositeSubscription 改名成了 CompositeDisposable
  • SerialSubscriptionMultipleAssignmentSubscription被合并到了SerialDisposable里. set() 方法会处理掉就的值,而replace()方法不会。
  • RefCountSubscription被移除了

Backpressure

在第一节Observable and Flowable里已经说到了这个问题,在2中,Observable将不会处理backpressure,也就不会发生MissingBackpressureException问题,但内存仍然会缓存多余的数据。

而在使用Flowable时,如果配置Backpressure有问题,那么MissingBackpressureException依然存在


Schedulers

RxJava2里仍然包含了computation, io, newThreadtrampoline这些默认线程调度。而immediate被移除了,因为他经常被人错误使用。同时Schedulers.test也被移除了。


Entering the reactive world

将普通方法转换成RxJava的数据源,在RxJava1中,提供了Observable.create()方法,但是这个方法过于强大,但使用时需要注意的东西太多经常会发生错误。

因此在RxJava2中,把原来的fromAsync重命名成了createfromAsync是一个和create类似但更为简单和安全的方法。这样大部分旧代码都能够继续使用。


Leaving the reactive world

之前如果想把数据源转换成普通的数据对象,需要先转换成BlockingObservable。而在2中,可以调用blockingXXX方法直接把数据源转换成对象:

List<Integer> list = Flowable.range(1, 100).toList().blockingFirst();

有一点需要特别注意,在RxJava2里,不建议在Subscriber里抛出错误,这意味着下面的代码可能有一天就不能继续运行了:

Subscriber<Integer> subscriber = new Subscriber<Integer>() {
    @Override
    public void onSubscribe(Subscription s) {
        s.request(Long.MAX_VALUE);
    }

    public void onNext(Integer t) {
        if (t == 1) {
            throw new IllegalArgumentException();
        }
    }

    public void onError(Throwable e) {
        if (e instanceof IllegalArgumentException) {
            throw new UnsupportedOperationException();
        }
    }

    public void onComplete() {
        throw new NoSuchElementException();
    }
};

Flowable.just(1).subscribe(subscriber);

由于上面类似的代码实际中出现得很多,因此在2中提供了safeSubscribe方法,使用它就可以继续在subscriber里抛出错误。

当然,你可以绕过subscribe(subscriber)这个方法,使用类似:

Flowable.just(1).subscribe(subscriber::onNext, subscriber::onError, subscriber::onComplete);

这样的方法,之前的代码仍然可以继续throw错误。


Operator differences

操作符的改动不大,大部分是扩充了参数数量。
或者是加入prefetch代表可以加入预置数据。


总结

可以明显的看到,RxJava2最大的改动就是对于backpressure的处理,为此将原来的Observable拆分成了新的ObservableFlowable,同时其他相关部分也同时进行了拆分。

除此之外,他和我们最熟悉和喜爱的RxJava~


引用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容