RxJava背压基础讲解
https://blog.csdn.net/weixin_37730482/article/details/78085190
本章节继续讲述RxJava的背压问题
一.控制 观察者 接收事件的速度
<1> 前言
当被观察者发送消息的速度和观察者接收消息的速度不匹配时,可以控制观察者接收消息的速度。
原理是 不管被观察者发送了多少条数据,观察者仅根据自身情况选择接收几条消息。哪怕被观察者发送量100条数据,若观察者仅需要两条消息,则只接收两条消息。忽略另外98条消息。
<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()) {
for (int i = 0; i < 5; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
}
e.onComplete();
}
}
}, 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(4);//测试 被观察者发送五条消息 观察者只接收四条
}
@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", "退出页面 取消订阅");
}
}
}
<3> 结果
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 波数据
<4> 说明
被观察者发送五条消息。观察者通过onSubscribe方法中参数Subscription的request(number)方法设置只接收number即四条消息。
<5> 重要说明&异步订阅
Flowable抽象类创建被观察者方式 如果被观察者和观察者是异步订阅的 如果不设置
mSubscription.request(N);//设置 观察者只接收N条数据
则说明 观察者不接收消息。此时 被观察者仍然可以发送消息。并将消息存在缓存区。等待观察者需要时再取出。即调用
mSubscription.request(N);//设置 观察者只接收N条数据
方法。
(1) 代码
package com.example.mydemo.rxjava;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
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);
findView();
method();
}
/**
* 初始化各种View
*/
private void findView() {
TextView textView = findViewById(R.id.activity_rxjava_textview);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (null != mSubscription) {
mSubscription.request(4);//观察者只接收四条
}
}
});
}
/**
* 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 < 5; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
}
e.onComplete();
}
}
}, 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;
}
@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", "退出页面 取消订阅");
}
}
}
(2) 结果
默认
无打印 即无消息接收
点击按钮 点击第一次 取出四条消息。
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 波数据
点击按钮 点击第二次 取出剩余消息并执行onComplete方法。
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 4 波数据
D/TAG: Flowable创建被观察者 观察者 onComplete方法
点击按钮 点击第三四五...次
无打印 即无消息接收。
<6> 重要说明&同步订阅
同步订阅,即被观察者和观察者处在同一线程中。同步订阅关系中没有缓存区。
同步订阅&异步订阅区别
订阅关系 | 说明 |
同步订阅 | 观察者和被观察者处在同一线程。被观察者每发送一条消息。必须等到观察者接收后才会发送下一条消息。 |
异步订阅 | 观察者和被观察者处在不同的线程。被观察者不需要等待观察者处理消息后再发送下一条消息,而是不断发送直到发送消息完毕。 |
代码
[1] 被观察者发送的消息数和观察者设置接收的消息数一致时。
(1) 代码
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;
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 < 5; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
Log.d("TAG", "Flowable创建被观察者 被观察者发送数据 i----:" + i);
}
e.onComplete();
}
}
}, BackpressureStrategy.LATEST)
.subscribe(new Subscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
if (null == s) {
return;
}
mSubscription = s;
mSubscription.request(5);//观察者接收五条
}
@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", "退出页面 取消订阅");
}
}
}
(2) 结果
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 0 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:0
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 1 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:1
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 2 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:2
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 3 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:3
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 4 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:4
D/TAG: Flowable创建被观察者 观察者 onComplete方法
(3) 综上所述,同步订阅情况下不会出现被观察者发送事件速度 > 观察者接收事件速度的情况。可是,却会出现被观察者发送事件数量 > 观察者接收事件数量的问题。
[2] 被观察者发送的消息数和观察者设置接收的消息数不一致时。
(1) 代码
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;
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 < 5; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
Log.d("TAG", "Flowable创建被观察者 被观察者发送数据 i----:" + i);
}
e.onComplete();
}
}
}, BackpressureStrategy.LATEST)
.subscribe(new Subscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
if (null == s) {
return;
}
mSubscription = s;
mSubscription.request(3);//观察者接收三条
}
@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", "退出页面 取消订阅");
}
}
}
即 被观察者发送五条数据 观察者只接收三条消息。
(2) 结果
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 0 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:0
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 1 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:1
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 2 波数据
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:2
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:3
D/TAG: Flowable创建被观察者 被观察者发送数据 i----:4
(3) 综上所述 对于没有缓存区概念的同步订阅关系来说,单纯采用控制观察者的接收事件数量(响应式拉取)还是会出现问题。
[3] 点击时再执行观察者的取方法
(1) 代码
package com.example.mydemo.rxjava;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
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;
public class RxJavaActivity extends AppCompatActivity {
private Subscription mSubscription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxjava);
findView();
method();
}
/**
* 初始化各种View
*/
private void findView() {
TextView textView = findViewById(R.id.activity_rxjava_textview);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (null != mSubscription) {
mSubscription.request(4);//观察者只接收四条
}
}
});
}
/**
* 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 < 5; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
}
e.onComplete();
}
}
}, BackpressureStrategy.LATEST)
.subscribe(new Subscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
if (null == s) {
return;
}
mSubscription = s;
}
@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", "退出页面 取消订阅");
}
}
}
(2) 结果
默认
无打印 即无消息接收
点击按钮 第一次点击
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 4 波数据
D/TAG: Flowable创建被观察者 观察者 onComplete方法
点击按钮第二三四五...次点击
无打印 即无消息接收
二.控制 被观察者 发送事件的速度
<1> 前言
上述可知可以通过观察者的onSubscribe方法中参数Subscription的request(N)方法控制观察者可接收的消息数,继而控制观察者接收事件的速度。那么被观察者的发送事件的速度怎么控制呢?
源码分析
create操作符创建被观察者 重写 subscribe方法 该方法参数FlowableEmitter<Object> e 点击
public interface FlowableEmitter<T> extends Emitter<T> {
/**
* Sets a Disposable on this emitter; any previous Disposable
* or Cancellation will be unsubscribed/cancelled.
* @param s the disposable, null is allowed
*/
void setDisposable(Disposable s);
/**
* Sets a Cancellable on this emitter; any previous Disposable
* or Cancellation will be unsubscribed/cancelled.
* @param c the cancellable resource, null is allowed
*/
void setCancellable(Cancellable c);
/**
* The current outstanding request amount.
* <p>This method is thread-safe.
* @return the current outstanding request amount
*/
long requested();
/**
* Returns true if the downstream cancelled the sequence.
* <p>This method is thread-safe.
* @return true if the downstream cancelled the sequence
*/
boolean isCancelled();
/**
* Ensures that calls to onNext, onError and onComplete are properly serialized.
* @return the serialized FlowableEmitter
*/
FlowableEmitter<T> serialize();
}
可以看到 此参数可以判断是否取消订阅 isCancelled()方法。而request()方法可以获取被观察者中的消息数量。
<2> 同步订阅 控制被观察者发送消息速度
(1) 简介
同步订阅中,被观察者和观察者处在同一线程。被观察者中request方法得到的数等于观察者中Subscription.request()方法中设置的数。
(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;
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;
}
long msgNumber = e.requested();
Log.d("TAG", "Flowable创建被观察者 被观察者 msgNumber----:" + msgNumber);
if (!e.isCancelled()) {
for (int i = 0; i < msgNumber; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
}
e.onComplete();
}
}
}, BackpressureStrategy.LATEST)
.subscribe(new Subscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
if (null == s) {
return;
}
mSubscription = s;
mSubscription.request(5);//观察者设置可接收五条消息
}
@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", "退出页面 取消订阅");
}
}
}
(3) 结果
D/TAG: Flowable创建被观察者 被观察者 msgNumber----:5
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创建被观察者 观察者 onComplete方法
(4) 说明
{1} 被观察者的 e.requested();方法具有实时性。即被观察者发送了一条数据 e.requested();方法就会减一。
代码 在上基础上改动
long msgNumber = e.requested();
Log.d("TAG", "Flowable创建被观察者 被观察者 msgNumber----:" + msgNumber);
if (!e.isCancelled()) {
for (int i = 0; i < msgNumber; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
Log.d("TAG", "Flowable创建被观察者 被观察者 发送了i后e.requested()----:" + e.requested());
}
e.onComplete();
}
结果
D/TAG: Flowable创建被观察者 被观察者 msgNumber----:5
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 0 波数据
D/TAG: Flowable创建被观察者 被观察者 发送了i后e.requested()----:4
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 1 波数据
D/TAG: Flowable创建被观察者 被观察者 发送了i后e.requested()----:3
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 2 波数据
D/TAG: Flowable创建被观察者 被观察者 发送了i后e.requested()----:2
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 3 波数据
D/TAG: Flowable创建被观察者 被观察者 发送了i后e.requested()----:1
D/TAG: Flowable创建被观察者 观察者 onNext方法 o.toString()----:Flowable创建被观察者 被观察者发送第 4 波数据
D/TAG: Flowable创建被观察者 被观察者 发送了i后e.requested()----:0
D/TAG: Flowable创建被观察者 观察者 onComplete方法
{2} 观察者没有设置可接收事件数量,即无调用Subscription.request()。那么被观察者默认观察者可接收事件数量 = 0,即FlowableEmitter.requested()的返回值 = 0。
{3} 可叠加性
代码
mSubscription.request(5);//第一次设置 观察者设置可接收五条消息
mSubscription.request(10);//第二条设置 观察者设置可接收十条消息
结果 5+10=15
D/TAG: Flowable创建被观察者 被观察者 msgNumber----:15
<3> 异步订阅 控制被观察者发送消息速度
(1) 说明
异步订阅中,被观察者和观察者处在不同的线程。所以被观察者 无法通过 FlowableEmitter.requested()知道观察者自身接收事件能力。即 被观察者不能根据 观察者自身接收事件的能力 控制发送事件的速度。
被观察者中request方法得到的数==128,96,0。 和观察者中Subscription.request()方法中设置的数不相等。
(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;
}
long msgNumber = e.requested();
Log.d("TAG", "Flowable创建被观察者 被观察者 msgNumber----:" + msgNumber);
if (!e.isCancelled()) {
for (int i = 0; i < msgNumber; i++) {
e.onNext("Flowable创建被观察者 被观察者发送第 " + i + " 波数据");
}
e.onComplete();
}
}
}, BackpressureStrategy.LATEST)
.subscribeOn(Schedulers.io())//被观察者 IO线程
.observeOn(AndroidSchedulers.mainThread())//观察者 UI线程
.subscribe(new Subscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
if (null == s) {
return;
}
mSubscription = s;
mSubscription.request(5);//观察者设置可接收五条消息
}
@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", "退出页面 取消订阅");
}
}
}
(3) 结果
D/TAG: Flowable创建被观察者 被观察者 msgNumber----:128
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 波数据
即 观察者设置可以接收的消息数是五条,但是被观察者中请求的消息数是128。
三.Flowable其他操作符使用背压策略
<1> 前言
上述的讲解都是使用的Flowable的create操作符创建的被观察者,那么背压策略可以在第二个参数传入。如下。
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);
那么使用其他的操作符呢,比如前节讲的interval操作符。下面讲解。
<2> 代码
package com.wjn.rxdemo.rxjava;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.wjn.rxdemo.R;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import java.util.concurrent.TimeUnit;
import io.reactivex.Flowable;
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创建被观察者 背压
*/
private void method() {
Flowable.interval(1, TimeUnit.MILLISECONDS)
.onBackpressureBuffer() // 添加背压策略封装好的方法,此处选择Buffer模式,即缓存区大小无限制
.observeOn(Schedulers.newThread())
.subscribe(new Subscriber<Long>() {
@Override
public void onSubscribe(Subscription s) {
if (null == s) {
return;
}
mSubscription = s;
s.request(Long.MAX_VALUE);//观察者设置可接收最多条数的消息
}
@Override
public void onNext(Long aLong) {
if (null == aLong) {
return;
}
Log.d("TAG", "Flowable创建被观察者 观察者 onNext方法 aLong----:" + aLong);
//模拟1秒接收
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@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", "退出页面 取消订阅");
}
}
}
<3> 结果
D/TAG: Flowable创建被观察者 观察者 onNext方法 aLong----:0
D/TAG: Flowable创建被观察者 观察者 onNext方法 aLong----:1
D/TAG: Flowable创建被观察者 观察者 onNext方法 aLong----:2
D/TAG: Flowable创建被观察者 观察者 onNext方法 aLong----:3
D/TAG: Flowable创建被观察者 观察者 onNext方法 aLong----:4
D/TAG: Flowable创建被观察者 观察者 onNext方法 aLong----:5
<4> 关闭页面
D/TAG: 退出页面 取消订阅
<5> 说明
上述代码中有这样的设置
.onBackpressureBuffer() // 添加背压策略封装好的方法,此处选择Buffer模式,即缓存区大小无限制
那么还有没有其他的设置呢,以及每个设置对应的含义是什么呢。
举例 | 含义 | 对create操作符 |
.onBackpressureBuffer() | 缓存区满时 将缓存区设置无限大 注意内存溢出 | BUFFER |
.onBackpressureDrop() | 缓存区满时 事件丢失 保留[0,127]条数据 即 前 128条数据 | DROP |
onBackpressureLatest() | 缓存区满时 事件丢失 保留[0,127]条数据+超出的最后一条数据 | LATEST |
四.总结
<1> RxJava的背压可以使用Flowable创建被观察者来实现。背压的使用大前提是 异步订阅中,观察者和被观察者发送消息的速度或者数量不匹配,一般是被观察者发送的速度太快或者消息太多,观察者来不及处理。
<2> 背压一般应用在被观察者和观察者异步订阅时,因为同步订阅正式项目很少使用。(RxJava核心就是异步嘛)。
<3> 其实一般使用RxJava实现异步,只要注意在适当的时机取消订阅,防止内存泄漏即可。没必要使用背压。
<4> 其实处理被观察者和观察者匹配问题也可以有其他的操作办法,比如使用delay()操作符创建一个延时的被观察者。再比如使用interval操作符创建指定时间的被观察者等等。