Android RxJava学习记录(二)

(五)https://www.jianshu.com/p/0f2d6c2387c9

1、使用zip操作符,发送事件内容未组合前存放于“水缸”。

2、当上下游工作在同一个线程中时, 这时候是一个同步的订阅关系, 也就是说上游每发送一个事件必须等到下游接收处理完了以后才能接着发送下一个事件。

当上下游工作在不同的线程中时, 这时候是一个异步的订阅关系, 这个时候上游发送数据不需要等待下游接收。这时候就需要“水缸”了--上游把事件发送到水缸里去, 下游从水缸里取出事件来处理。若上游发事件的速度太快, 下游取事件的速度太慢, 水缸就会迅速装满, 然后溢出来, 最后就OOM了.

 

(六)https://www.jianshu.com/p/e4c6d7989356

解决(五)中上下游流速不均衡导致OOM的问题,解决方法有几种:

1、fliter操作符,筛出满足要求的事件放到“水缸”中

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                for (int i = 0; ; i++) {
                    emitter.onNext(i);
                }
            }
        }).subscribeOn(Schedulers.io())
                .filter(new Predicate<Integer>() {
                    @Override
                    public boolean test(Integer integer) throws Exception {
                        return integer % 10 == 0; //能被10整除的数可以通过
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.d(TAG, "" + integer);
                    }
});

2、sample操作符,取样,每隔指定的时间就从上游中取出一个事件发送给下游.

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                for (int i = 0; ; i++) {
                    emitter.onNext(i);
                }
            }
        }).subscribeOn(Schedulers.io())
                .sample(2, TimeUnit.SECONDS)  //sample取样
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.d(TAG, "" + integer);
                    }
                });

以上两种方法,减少了放进“水缸”的数量,缺点是:丢失了大部分事件。

其实,解决我们的问题,除了可以从数量上进行治理, 减少发送进水缸里的事件,还可以从速度上进行治理, 减缓事件发送进水缸的速度。

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                for (int i = 0; ; i++) {
                    emitter.onNext(i);
                    Thread.sleep(2000);  //每次发送完事件延时2秒
                }
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.d(TAG, "" + integer);
                    }
                });

 

(七)https://www.jianshu.com/p/9b1304435564

1、背压

rxjava2.x的Observable是不存在背压的概念的。背压,Backpressure,是下游控制上游流速的一种手段。在rxjava1.x的时代,上游会给下游set一个producer,下游通过producer向上游请求n个数据,这样上游就有记录下游请求了多少个数据,然后下游请求多少个上游就给多少个,这就是背压。在rxjava2.x时代,上述的背压逻辑全部挪到Flowable里了,所以说Flowable支持背压。而2.x时代的Observable是没有背压的概念的。官方文档建议,大数据流用Flowable,小数据流用Observable。

2、Flowable

使用Observable时上游和下游分别是ObservableObserver。使用Flowable时,上游变成了Flowable, 下游变成了Subscriber,订阅依然是通过subscribe。

Flowable<Integer> upstream = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<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();
            }
        }, BackpressureStrategy.ERROR); //增加了一个参数

        Subscriber<Integer> downstream = new Subscriber<Integer>() {

            @Override
            public void onSubscribe(Subscription s) {
                Log.d(TAG, "onSubscribe");
                s.request(Long.MAX_VALUE);  //注意这句代码
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "onNext: " + integer);

            }

            @Override
            public void onError(Throwable t) {
                 Log.w(TAG, "onError: ", t);
            }

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

upstream.subscribe(downstream);

注意: (1)创建Flowable时多了一个参数BackpressureStrategy.ERROR,这是一种背压策略,当出现上下游流速不均衡的时候会抛出一个异常 MissingBackpressureException

(2)下游的onSubscribe方法中传给我们的不再是Disposable了, 而是Subscription。调用Subscription.cancel()也可以切断水管,达到和 Disposable.dispose() 一样的效果。不过这里的Subscription增加了一个void request(long n)方法。

这里,Flowable采用了一种响应式拉取方式(背压)来解决流速不均衡问题。下游请求可以处理多少个,上游就给多少个,下游处理完了再请求,上游再给。

在同步,上下游处于相同线程中时,下游需要执行方法 Subscription.request(n),不然上游认为下游没有处理事件的能力,就会抛出异常MissingBackpressureException。异步时,上下游处于不同线程,下游未执行Subscription.request(n)是有可能不抛出异常MissingBackpressureException的,原因在于,Flowable默认有一个大小为128的“水缸”。当上下游工作在不同的线程中时, 上游就会先把事件发送到这个水缸中, 因此, 下游虽然没有调用request, 但是上游在水缸中保存着这些事件, 只有当下游调用request时, 才从水缸里取出事件发给下游.所以当上游事件数量少于128时是不会抛出异常的,即使超过了128,若下游发生请求了使“水缸”的数量一直处于128也是不会抛出异常的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KWMax

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值