RxJava详解(基于2.X版本的背压详解 )(上)

本文深入探讨了RxJava中的背压问题,详细介绍了背压产生的原因、背压策略的作用及其实现方式。通过对比Observable与Flowable的不同,阐述了如何使用Flowable来有效地处理背压,并提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本章节讲述RxJava的背压问题。

 

 

一.背景

 

<1> 前言

 

RxJava是一种扩展的观察者模式。观察者被观察者发生订阅后。可以时刻观察被观察者。被观察者发生变化时,观察者会收到相关的消息。

 

RxJava中观察者和被观察者发生订阅,可以同步也可以异步

 

异步订阅时,如果被观察者短时间内连续发送多条onNext消息观察者可能来不及接收。这就会出现被观察者和观察者消息不匹配的问题。从而导致观察者无法及时响应&处理所有发送过来事件的消息。最终可能导致缓存区溢出或者事件丢失。这种问题要解决,那怎么解决呢?背压解决,那么背压策略是什么呢。

 

 

 

<2> 背压策略简介

 

控制事件流速。即控制被观察者发送事件速度和观察者接收事件的速度

 

 

 

<3>背压策略作用

异步订阅关系 中,控制事件发送事件接收的速度。注意背压的使用观察者和被观察者一定要是异步订阅的

 

 

 

<4>背压策略的具体实现

在 RxJava2.X版本中采用 Flowable(非阻塞式背压) 实现 背压策略。

 

 

 

<5> Flowable与Observable的区别

上面提到可以使用Flowable创建被观察者。而前几篇连载的RxJava内容讲述都是使用的Observable创建被观察者。那么两者有什么区别呢。

 

Observable 在 RxJava2.X版本 中新的实现叫做 Flowable。同时旧的Observable也保留了。因为在 RxJava 1.x版本中,有很多事件不被能正确的背压,从而抛出MissingBackpressureException。

比如

 

在RxJava1.x版本中的 observeOn,因为是切换了消费者的线程,因此内部实现用队列存储事件。在 Android 中默认的 buffersize 大小是16,因此当消费比生产慢时, 队列中的数目积累到超过16个,就会抛出MissingBackpressureException。

 

在RxJava2.x版本中的 Observable 不再支持背压,而Flowable支持非阻塞式的背压。Flowable是RxJava2.0中专门用于应对背压(Backpressure)问题。

 

所谓背压,即生产者的速度大于消费者的速度带来的问题,比如在Android中常见的点击事件,点击过快则经常会造成点击两次的效果。其中,Flowable默认队列大小为128。并且规范要求,所有的操作符强制支持背压。幸运的是, Flowable 中的操作符大多与旧有的 Observable 类似。

 

 

 

 

 

 

 

二.基础代码&说明

 

<1> Gradle配置

implementation 'io.reactivex.rxjava2:rxjava:2.0.7'

implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

说明

[1] RxJava&RxAndroid 版本须一致 即都是2.x版本

RxAndroid 必须依赖对应版本的RxJava。官方解释。

Because RxAndroid releases are few and far between, it is recommended you also
explicitly depend on RxJava's latest version for bug fixes and new features.

[2] 因为之前项目中使用的是2.0.1版本,所以好多与背压相关的类找不到。这里改成2.0.7版本即可。

[3] 发现一些所处的包位置不同

 

比如 Flowable类

 

比如 Subscriber类

 

 

 

<2> 基础代码

package com.example.mydemo.rxjava;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import com.example.mydemo.R;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

public class RxJavaActivity extends AppCompatActivity {

    private Subscription mSubscription;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxjava);

        method();
    }

    /**
     * RxJava Flowable创建被观察者 背压
     */

    public void method() {

        Flowable.create(new FlowableOnSubscribe<Object>() {
            @Override
            public void subscribe(FlowableEmitter<Object> e) throws Exception {
                if (null == e) {
                    return;
                }

                if (!e.isCancelled()) {
                    e.onNext("Flowable创建被观察者 被观察者发送第1波数据");
                    e.onNext("Flowable创建被观察者 被观察者发送第2波数据");
                    e.onNext("Flowable创建被观察者 被观察者发送第3波数据");
                    e.onComplete();
                }

                Log.d("TAG", "Flowable创建被观察者 被观察者 subscribe方法 线程----:" + Thread.currentThread().getName());
            }
        }, BackpressureStrategy.LATEST)
                .subscribeOn(Schedulers.io())//被观察者在io线程中进行
                .observeOn(AndroidSchedulers.mainThread())//观察者在主线程中进行
                .subscribe(new Subscriber<Object>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        if (null == s) {
                            return;
                        }
                        mSubscription = s;
                        mSubscription.request(Long.MAX_VALUE);
                    }

                    @Override
                    public void onNext(Object o) {
                        if (null == o) {
                            return;
                        }
                        Log.d("TAG", "Flowable创建被观察者 观察者 onNext方法 o.toString()----:" + o.toString());
                        Log.d("TAG", "Flowable创建被观察者 观察者 onNext方法 线程----:" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable t) {
                        if (null == t) {
                            return;
                        }
                        Log.d("TAG", "Flowable创建被观察者 观察者 onError方法 t.toString()----:" + t.toString());
                        Log.d("TAG", "Flowable创建被观察者 观察者 onError方法 线程----:" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onComplete() {
                        Log.d("TAG", "Flowable创建被观察者 观察者 onComplete方法 ");
                        Log.d("TAG", "Flowable创建被观察者 观察者 onComplete方法 线程----:" + Thread.currentThread().getName());
                    }
                });
    }

    /**
     * onDestroy方法 取消订阅
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != mSubscription) {
            mSubscription.cancel();
            Log.d("TAG", "退出页面 取消订阅");
        }
    }

}

 

 

<3> 结果

D/TAG: Flowable创建被观察者 被观察者 subscribe方法 线程----:RxCachedThreadScheduler-1



D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第1波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 线程----:main



D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第2波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 线程----:main



D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第3波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 线程----:main



D/TAG: Flowable创建被观察者 观察者 onComplete方法 

D/TAG: Flowable创建被观察者 观察者 onComplete方法 线程----:main

 

 

<4> 关闭页面

D/TAG: 退出页面 取消订阅

 

 

<5> 说明

使用Flowable抽象类创建被观察者和使用Observable抽象类创建被观察者还是有一些不同的。

 

比如create操作符时传入了第二个参数BackpressureStrategy.LATEST

 

再比如观察者的onSubscribe方法中参数是Subscription类型。会继续讲解。

 

 

 

 

 

 

三.BackpressureStrategy参数具体讲解

 

上述使用Flowable抽象类创建被观察者 需要传两个参数。

 

源码

public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
    ObjectHelper.requireNonNull(source, "source is null");
    ObjectHelper.requireNonNull(mode, "mode is null");
    return RxJavaPlugins.onAssembly(new FlowableCreate<T>(source, mode));
}

 

参数2:枚举 BackpressureStrategy mode 具体有哪些值呢,每个值又是什么含义呢。下面讲解。

 

<1> BackpressureStrategy 取值&含义

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
}
字段含义
MISSING缓存区满友好提示
ERROR缓存区满直接抛异常
BUFFER缓存区满将缓存区设置无限大 注意内存溢出
DROP缓存区满事件丢失 保留[0,127]条数据 即 前 128条数据
LATEST缓存区满事件丢失 保留[0,127]条数据+超出的最后一条数据

 

 

 

 

 

 

 

 

 

<2>  具体代码说明

上述可知使用Flowable抽象类创建被观察者 默认缓存大小128

 

[1] BackpressureStrategy.MISSING 模式

代码

package com.example.mydemo.rxjava;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import com.example.mydemo.R;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

public class RxJavaActivity extends AppCompatActivity {

    private Subscription mSubscription;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxjava);

        method();
    }

    /**
     * RxJava Flowable创建被观察者 背压
     */

    public void method() {

        Flowable.create(new FlowableOnSubscribe<Object>() {
            @Override
            public void subscribe(FlowableEmitter<Object> e) throws Exception {
                if (null == e) {
                    return;
                }

                if (!e.isCancelled()) {
                    for (int i = 0; i < 150; i++) {
                        e.onNext("Flowable创建被观察者 被观察者发送第   " + i + "   波数据");
                    }
                    e.onComplete();
                }
            }
        }, BackpressureStrategy.MISSING)
                .subscribeOn(Schedulers.io())//被观察者在io线程中进行
                .observeOn(AndroidSchedulers.mainThread())//观察者在主线程中进行
                .subscribe(new Subscriber<Object>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        if (null == s) {
                            return;
                        }
                        mSubscription = s;
                        mSubscription.request(Long.MAX_VALUE);
                    }

                    @Override
                    public void onNext(Object o) {
                        if (null == o) {
                            return;
                        }
                        Log.d("TAG", "Flowable创建被观察者 观察者 onNext方法 o.toString()----:" + o.toString());
                    }

                    @Override
                    public void onError(Throwable t) {
                        if (null == t) {
                            return;
                        }
                        Log.d("TAG", "Flowable创建被观察者 观察者 onError方法 t.toString()----:" + t.toString());
                    }

                    @Override
                    public void onComplete() {
                        Log.d("TAG", "Flowable创建被观察者 观察者 onComplete方法 ");
                    }
                });
    }

    /**
     * onDestroy方法 取消订阅
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != mSubscription) {
            mSubscription.cancel();
            Log.d("TAG", "退出页面 取消订阅");
        }
    }

}

 

结果

D/TAG: Flowable创建被观察者 观察者 onError方法 t.toString()----:io.reactivex.exceptions.MissingBackpressureException: Queue is full?!

 

说明

使用 BackpressureStrategy.MISSING 模式时 当被观察者发出超出128条数据时  走了onError方法。具体错误提示如上。

 

 

 

[2] BackpressureStrategy.ERROR 模式

修改上述代码 背压模式为 BackpressureStrategy.ERROR 模式 其他不变。

 

结果

D/TAG: Flowable创建被观察者 观察者 onError方法 t.toString()----:io.reactivex.exceptions.MissingBackpressureException: create: could not emit value due to lack of requests

 

说明

使用 BackpressureStrategy.ERROR 模式 时 当被观察者发出超出128条数据时  走了onError方法。具体错误提示如上。

 

 

 

[3] BackpressureStrategy.BUFFER 模式

修改上述代码 背压模式为 BackpressureStrategy.BUFFER 模式 其他不变。

 

结果

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   0   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   1   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   2   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   3   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   4   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   5   波数据


...


D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   145   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   146   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   147   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   148   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   149   波数据


D/TAG: Flowable创建被观察者 观察者 onComplete方法 

 

说明

使用 BackpressureStrategy.BUFFER 模式 时 当被观察者发出超出128条数据时  流程正常。全部输出包括超出的部分消息。

 

 

 

[4] BackpressureStrategy.DROP 模式

修改上述代码 背压模式为 BackpressureStrategy.DROP 模式 其他不变。

 

结果

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   0   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   1   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   2   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   3   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   4   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   5   波数据


...


D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   123   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   124   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   125   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   126   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   127   波数据


D/TAG: Flowable创建被观察者 观察者 onComplete方法 

 

说明

使用 BackpressureStrategy.DROP 模式 时 当被观察者发出超出128条数据时  流程正常。输出[0,127]条数据。

 

 

 

 

[5] BackpressureStrategy.LATEST 模式

修改上述代码 背压模式为 BackpressureStrategy.LATEST 模式 其他不变。

 

结果

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   0   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   1   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   2   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   3   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   4   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   5   波数据


...


D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   123   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   124   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   125   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   126   波数据

D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   127   波数据



D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第   149   波数据


D/TAG: Flowable创建被观察者 观察者 onComplete方法 

 

说明

使用 BackpressureStrategy.LATEST 模式 时 当被观察者发出超出128条数据时  流程正常。输出[0,127]条数据+最后一条数据。

 

 

 

<3> 总结

BackpressureStrategy枚举类的使用,只在被观察者发送的消息数量超过默认缓存量128。才有效果。

 

 

 

<4> 更多RxJava背压讲解

https://blog.youkuaiyun.com/weixin_37730482/article/details/78086361

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值