笔记1操作符的介绍:Rxjava2的笔记1 --操作符_observable.just传入多参数-CSDN博客
参考视频:https://edu.csdn.net/course/play/10037/213573
基本响应类型
Observable:最基本的响应类型,不支持背压
背压是什么
背压就是上游发送数据的速度很快,下游没有来得及处理,就会累积很多数据;在高并发的时候会发生背压
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("123");
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.e(TAG, "onNext: " + s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete: " );
}
});
Flowable和Observable使用基本类似,Observable不支持背压,Flowable支持背压,使用Flowable的时候,必须调用Subscription的request的方法请求
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
emitter.onNext("123");
emitter.onNext("456");
emitter.onNext("789");
emitter.onComplete();
}
//背压策略
}, BackpressureStrategy.DROP)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
//下游可以接受2个数据
s.request(2);
}
@Override
public void onNext(String s) {
Log.e(TAG, "onNext: " + s );
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete: " );
}
});
Single:只发射一个元素的相应类型,发射onSuccess或者onError方法
Single.create(new SingleOnSubscribe<String>() {
@Override
public void subscribe(SingleEmitter<String> emitter) throws Exception {
emitter.onSuccess("success");
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(String s) {
Log.e(TAG, "onSuccess: " );
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: ");
}
});
Completable:仅仅给下游一个信号的响应类型,回调onComplete或者onError
Completable.create(new CompletableOnSubscribe() {
@Override
public void subscribe(CompletableEmitter emitter) throws Exception {
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete: " );
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " );
}
});
Maybe:Single和Completable的结合,信号和数据的结合,但也只能接收到其中的一员
Maybe.create(new MaybeOnSubscribe<String>() {
@Override
public void subscribe(MaybeEmitter<String> emitter) throws Exception {
emitter.onSuccess("success");
emitter.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new MaybeObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(String s) {
Log.e(TAG, "onSuccess: ");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: ");
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete: ");
}
});
Rxjava的背压策略
背压是什么
背压在高并发中较为常见,在异步场景中,由于数据流的发射速度大于数据流的接收速度,导致数据不能及时接收,从而导致数据流的阻塞,背压所要做的就是主动控制数据流发射的速度.
Rxjava2中使用Flowable用来支持背压,Observable对背压不支持
1.在订阅的时候如果使用FlowableSubscriber,需要通过s.request(Long.MAX_VALUE)去主动请求上游的数据项,遇到背压报错的时候,FlowableSubscriber默认已经将错误try-catch,并通过onError回调,程序并不会崩溃;
2.在订阅的时候如果使用Consumer,那么不需要主动去请求上游数据,默认已经调用了s.request(Long.MAX_VALUE),如果遇到背压报错,且对Throwable的Consumer没有new出来,则程序直接崩溃;
3.背压策略上游的缓存池默认为128
MISSING:表示OnNext对事件没有任何的缓存和丢弃,下游要处理任何溢出,其实可以理解为没有背压,所以超出128的就会异常
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < 129; i++) {
emitter.onNext(i);
}
}
}, BackpressureStrategy.MISSING)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "onNext: " + integer );
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError: " + t.getMessage() );
}
@Override
public void onComplete() {
}
});
可以看到0-128共129个,超出128了,所以异常,但是因为是Flowable,所以会try-catch住,回调到onError
ERROR:下游无法跟上上游的发射速度时,会抛出异常
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < 129; i++) {
emitter.onNext(i);
}
}
}, BackpressureStrategy.ERROR)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "onNext: " + integer );
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError: " + t.getMessage() );
}
@Override
public void onComplete() {
}
});
无法发出第129个数据
BUFFER:上游不断的发出onNext请求,直到下游处理完,上游发射的数据项的缓存池是无限大的,程序也不会抛错误,但是由于缓存占用内存,所以可能出现OOM-内存溢出现象
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < 129; i++) {
emitter.onNext(i);
}
}
}, BackpressureStrategy.BUFFER)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "onNext: " + integer );
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError: " + t.getMessage() );
}
@Override
public void onComplete() {
}
});
可以看到129个数据全部发了出来
DROP:对于多余的数据会丢弃掉
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < 129; i++) {
emitter.onNext(i);
}
}
}, BackpressureStrategy.DROP)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "onNext: " + integer );
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError: " + t.getMessage() );
}
@Override
public void onComplete() {
}
});
latest:除了128个数据之外,还会把最后一个数据也放入缓存池中
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < 130; i++) {
emitter.onNext(i);
}
}
}, BackpressureStrategy.LATEST)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new FlowableSubscriber<Integer>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "onNext: " + integer );
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError: " + t.getMessage() );
}
@Override
public void onComplete() {
}
});
为了明显,我把数据发射了130个,所以最后一个也
实战1 - 模拟发送验证码
这里面的操作符有不会的可以去看笔记1
private void initRxjava1() {
mButton = findViewById(R.id.button);
mButton.setText("点击发送验证码");
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
verify();
}
});
}
@SuppressLint("CheckResult")
private void verify() {
final int count = 3; //倒计时3秒
Observable.interval(0,1, TimeUnit.SECONDS)
.take(count+1) //0,1,2,3
.map(new Function<Long, Long>() {
@Override
public Long apply(Long aLong) throws Exception {
return count - aLong; //转换为3,2,1,0
}
})
.observeOn(AndroidSchedulers.mainThread())
//监听生命周期
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
mButton.setEnabled(false);
}
})
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
//在0秒的时候会调用到complete,所以没有显示剩余0秒
mButton.setText("剩余" + aLong+"秒");
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
}
}, new Action() {
@Override
public void run() throws Exception {
//onComplete事件
mButton.setEnabled(true);
mButton.setText("点击发送验证码");
}
});
}
运行结果:
实战2.防止用户多次点击
throttleFirst这个属性
private void initView() {
mButton = findViewById(R.id.button);
query(mButton);
}
public void query(View view) {
RxUtils.click(view, 2)
.subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Object o) {
Log.e(TAG, "onNext: ");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete: ");
}
});
}
static class RxUtils {
//非静态内部类不能有静态方法
public static Observable<Object> click(final View view, long seconds) {
return new ViewClickObservable(view)
//2秒内只接受第一次点击
.throttleFirst(2, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
if (view !=null){
view.setOnClickListener(null);
}
}
});
}
}
static class ViewClickObservable extends Observable<Object> {
private View mView;
public ViewClickObservable(View view) {
this.mView = view;
}
@Override
protected void subscribeActual(Observer<? super Object> observer) {
if (mView != null) {
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
observer.onNext(mView);
}
});
}
}
}
第二种写法,前面是对Observable的重写,这个是对ObservableOnSubscribe的重写
@SuppressLint("CheckResult")
private void initView() {
mButton = findViewById(R.id.button);
query(mButton);
}
public void query(View view) {
RxUtils.click(view, 2)
.subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Object o) {
Log.e(TAG, "onNext: ");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete: ");
}
});
}
static class ViewClickObservableOnSubscribe implements ObservableOnSubscribe<Object> {
ObservableEmitter<Object> mEmitter;
public ObservableEmitter<Object> getEmitter() {
return mEmitter;
}
@Override
public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
mEmitter = emitter;
}
}
static class RxUtils {
//非静态内部类不能有静态方法
public static Observable<Object> click(final View view, long seconds) {
ViewClickObservableOnSubscribe viewClickObservableOnSubscribe = new ViewClickObservableOnSubscribe();
if (view !=null){
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ObservableEmitter<Object> emitter = viewClickObservableOnSubscribe.getEmitter();
emitter.onNext(view);
}
});
}
return Observable.create(viewClickObservableOnSubscribe)
.throttleFirst(2, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
if (view != null) {
view.setOnClickListener(null);
}
}
});
}
}
运行效果:在2秒内点击多次,但只接受第一次的点击
实战3 : 模拟会员信息的合并
需求:获取列表中的会员信息,当本地有缓存时,就从本地获取信息,否则就从网络获取
public static class Vip {
}
//用来本地缓存会员信息的map
private HashMap<Long, Vip> mVipCache = new HashMap<>();
//获取列表的方法
public Observable<HashMap<Long, Vip>> getVipList(List<Long> uids) {
List<Long> vipRequest = new ArrayList<>();
HashMap<Long, Vip> vipLocal = new HashMap<>();
for (Long uid : uids) {
if (mVipCache.containsKey(uid)) {
Log.e(TAG, "从本地获取数据 " + uid + "用户");
vipLocal.put(uid, mVipCache.get(uid));
} else {
Log.e(TAG, "从网络获取数据 " + uid + "用户");
vipRequest.add(uid);
}
}
if (vipRequest.isEmpty()) {
return Observable.just(vipLocal);
}
return Observable.merge(Observable.just(vipLocal), getVipFromWeb(vipRequest));
}
//从网络获取列表的方法
public Observable<HashMap<Long, Vip>> getVipFromWeb(List<Long> uids) {
HashMap<Long, Vip> vipList = new HashMap<>();
for (Long uid : uids) {
Vip vip1 = new Vip();
vipList.put(uid, vip1);
}
//缓存到本地
mVipCache.putAll(vipList);
return Observable.just(vipList);
}
public void initData() {
List<Long> uids = new ArrayList<>();
Log.e(TAG, "第一次查询: ");
uids.add(1L);
uids.add(2L);
getVipList(uids);
uids.clear();
Log.e(TAG, "第二次查询: ");
uids.add(1L);
uids.add(2L);
uids.add(3L);
uids.add(4L);
getVipList(uids);
uids.clear();
Log.e(TAG, "第三次查询 ");
uids.add(1L);
uids.add(2L);
uids.add(3L);
uids.add(4L);
mVipCache.clear();
getVipList(uids);
}