Rxjava2.0解决背压策略学习总结

前言:

对于Rxjava大家并不陌生,它是基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大Android 开发者的欢迎。

对于RxJava中,观察者和被观察者具有两种订阅模式,及同步订阅,异步订阅;

同步订阅:即在同一线程中,被观察者每发一件事件,必须等到观察者接受处理后,才能发送下一个事件


异步订阅:观察者和被观察者不在同一个线程中,即产生了被观察者发送事件的速度与观察者接受事件的速度不一致,大多数情况是被观察者发送事件的速度大于观察者接受事件的速度,这个就是产生背压的原因.

RxJava2.0在RxJava1.0的基础上,采用背压策略来解决:因被观察者发送事件速度 与 观察者接收事件速度不匹配(一般是前者 快于 后者),从而导致观察者无法及时响应 / 处理所有 被观察者发送事件 的问题.

正文:

在RxJava2中真正实现背压策略的类是: Flowable,它是Observable的一种新实现.Flowable简单的使用如下:

//Flowable创建被观察者
Flowable.create(new FlowableOnSubscribe<Integer>() {
    @Override
    public void subscribe(@NonNull FlowableEmitter<Integer> emitter) throws Exception {
        emitter.onNext(1);
        emitter.onComplete();

    }
}, BackpressureStrategy.ERROR)//需要传入的被压参数
        .subscribeOn(Schedulers.io())//设置悲观者在子线程中
        .observeOn(AndroidSchedulers.mainThread())//设置观察者在主线程中
        //进行订阅
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {

                //制定观察者接受事件的个数(响应式拉取),默认是最大
                s.request(Long.MAX_VALUE);

            }

            @Override
            public void onNext(Integer integer) {

                Log.d("TAG","接受数据:" + integer);

            }

            @Override
            public void onError(Throwable t) {

            }

            @Override
            public void onComplete() {

            }
        });

接下来通过背压策略的原理及Flowable的使用,来说明RxJava2如何通过Flowable来解决背压问题

1.控制观察者接受事件的速度-------------------------------响应式拉取

即当观察者设置s.request()方法之后,即设置了观察者接受事件的个数

// 创建被观察者Flowable
Flowable.create(new FlowableOnSubscribe<Integer>() {
    @Override
    public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
        // 一共发送4个事件
        Log.d("TAG", "发送事件 1");
        emitter.onNext(1);
        Log.d("TAG", "发送事件 2");
        emitter.onNext(2);
        Log.d("TAG", "发送事件 3");
        emitter.onNext(3);
        Log.d("TAG", "发送事件 4");
        emitter.onNext(4);
        Log.d("TAG", "发送完成");
        emitter.onComplete();
    }
}, BackpressureStrategy.ERROR).subscribeOn(Schedulers.io()) // 设置被观察者在io线程中进行
        .observeOn(AndroidSchedulers.mainThread()) // 设置观察者在主线程中进行
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                // 对比Observer传入的Disposable参数,Subscriber此处传入的参数 = Subscription
                // 相同点:Subscription参数具备Disposable参数的作用,即Disposable.dispose()切断连接, 同样的调用Subscription.cancel()切断连接
                // 不同点:Subscription增加了void request(long n)

                s.request(3);//设置观察者只接受3个事件
                // 作用:决定观察者能够接收多少个事件
                // 如设置了s.request(3),这就说明观察者能够接收3个事件(多出的事件存放在缓存区)
                // 官方默认推荐使用Long.MAX_VALUE,即s.request(Long.MAX_VALUE);
            }

            @Override
            public void onNext(Integer integer) {
                Log.d("TAG", "接收到了事件" + integer);
            }

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

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

那么,问题来了,当观察者不设置s.request()方法,会出现什么呢?

当观察者不设置接受事件的个数时,被观察者依然会发送事件,只不过该事件会存入缓存区(大小128,这个大小可以查看Flowable源码)当如果发送的事件个数大于缓存区大小,即就会抛出异常.

// 创建被观察者Flowable
Flowable.create(new FlowableOnSubscribe<Integer>() {
    @Override
    public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
       for (int i = 0 ; i < 129; i ++){
           emitter.onNext(i);
       }

        emitter.onComplete();
    }
}, BackpressureStrategy.ERROR).subscribeOn(Schedulers.io()) // 设置被观察者在io线程中进行
        .observeOn(AndroidSchedulers.mainThread()) // 设置观察者在主线程中进行
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                // 对比Observer传入的Disposable参数,Subscriber此处传入的参数 = Subscription
                // 相同点:Subscription参数具备Disposable参数的作用,即Disposable.dispose()切断连接, 同样的调用Subscription.cancel()切断连接
                // 不同点:Subscription增加了void request(long n)

             //   s.request(3);//设置观察者只接受3个事件
                // 作用:决定观察者能够接收多少个事件
                // 如设置了s.request(3),这就说明观察者能够接收3个事件(多出的事件存放在缓存区)
                // 官方默认推荐使用Long.MAX_VALUE,即s.request(Long.MAX_VALUE);
            }

            @Override
            public void onNext(Integer integer) {
                Log.d("TAG", "接收到了事件" + integer);
            }

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

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

2.控制被观察者发送事件的速度----------------------------反馈控制

1>在同步订阅中,因为观察者和被观察者处于同一线程中,即被观察者可以得知观察者接受事件的个数,如下所示为FlowableEmitter部分源码,其中requested()方法即可获取观察者接受事件的个数

public interface FlowableEmitter<T> extends Emitter<T> {

    void setDisposable(@Nullable Disposable s);
    void setCancellable(@Nullable Cancellable c);
    /**
     * The current outstanding request amount.
     * <p>This method is thread-safe.
     * @return the current outstanding request amount
     */
    long requested();
    boolean isCancelled();
    @NonNull
    FlowableEmitter<T> serialize();
}

代码实现如下:

// 创建被观察者Flowable
Flowable.create(new FlowableOnSubscribe<Integer>() {
    @Override
    public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
        long requested = emitter.requested();
        Log.d("TAG","被观察者可以得知观察者接收事件的个数为:" + requested);
        for(int i = 0; i < requested; i ++ ){
            emitter.onNext(i);
        }
        emitter.onComplete();
    }
}, BackpressureStrategy.ERROR)
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                // 对比Observer传入的Disposable参数,Subscriber此处传入的参数 = Subscription
                // 相同点:Subscription参数具备Disposable参数的作用,即Disposable.dispose()切断连接, 同样的调用Subscription.cancel()切断连接
                // 不同点:Subscription增加了void request(long n)

                s.request(3);//设置观察者只接受3个事件
                // 作用:决定观察者能够接收多少个事件
                // 如设置了s.request(3),这就说明观察者能够接收3个事件(多出的事件存放在缓存区)
                // 官方默认推荐使用Long.MAX_VALUE,即s.request(Long.MAX_VALUE);
            }

            @Override
            public void onNext(Integer integer) {
                Log.d("TAG", "接收到了事件" + integer);
            }

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

            @Override
            public void onComplete() {
                Log.d("TAG", "onComplete");
            }
        });
2> 异步订阅,因为观察者和被观察者不在同一个线程中,所以被观察者无法获取观察者接受事件的个数,那么是如何解决的,这个问题及 采用背压策略模式:BackpressureStrategy稍后更新






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值