RxJava1.x从入门到放弃再到RxJava 2.x(四)
来源:互联网 发布:网络嗅探演示实验 编辑:程序博客网 时间:2024/05/16 10:25
Zip
Zip通过一个函数将多个Observable发送的事件结合到一起,然后发送这些组合到一起的事件. 它按照严格的顺序应用这个函数。它只发射与发射数据项最少的那个Observable一样多的数据。请看下面的图解。
上游有2支水管,分别从两根水管里各取出一个事件来进行组合, 并且一个事件只能被使用一次, 组合的顺序是严格按照事件发送的顺利进行的。
最终下游收到的事件数量是和上游中发送事件最少的那一根水管的事件数量相同. 这个也很好理解, 因为是从每一根水管 里取一个事件来进行合并, 最少的那个肯定就最先取完 , 这个时候其他的水管尽管还有事件 , 但是已经没有足够的事件来组合了, 因此下游就不会收到剩余的事件了。
Show me the code
//上游的水管“A” Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> e) throws Exception { Log.d(TAG, "emit 1"); e.onNext(1); Thread.sleep(100); Log.d(TAG, "emit 2"); e.onNext(2); Thread.sleep(100); Log.d(TAG, "emit 3"); e.onNext(3); Thread.sleep(100); Log.d(TAG, "emit 4"); e.onNext(4); Thread.sleep(100); Log.d(TAG, "emit complete1"); e.onComplete(); } }).subscribeOn(Schedulers.newThread()); //上游的水管“B” Observable<String> observable2 = Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { Log.d(TAG, "emit one"); e.onNext("one"); Thread.sleep(100); Log.d(TAG, "emit two"); e.onNext("two"); Thread.sleep(100); Log.d(TAG, "emit three"); e.onNext("three"); Thread.sleep(100); Log.d(TAG, "emit complete2"); e.onComplete(); } }).subscribeOn(Schedulers.newThread()); Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() { @Override public String apply(Integer integer, String s) throws Exception { return integer + " = " + s; } }).subscribe(new Observer<String>() { @Override public void onSubscribe(Disposable d) { Log.d(TAG, "onSubscribe"); } @Override public void onNext(String value) { Log.d(TAG, "onNext :" + value); } @Override public void onError(Throwable e) { Log.d(TAG, "onError :" + e.getMessage()); } @Override public void onComplete() { Log.d(TAG, "onComplete"); } });
05-21 06:03:16.100 19473-19473/com.example.administrator.testdemo D/tag: onSubscribe05-21 06:03:16.104 19473-19503/com.example.administrator.testdemo D/tag: emit 105-21 06:03:16.105 19473-19504/com.example.administrator.testdemo D/tag: emit one05-21 06:03:16.105 19473-19504/com.example.administrator.testdemo D/tag: onNext :1 = one05-21 06:03:16.205 19473-19504/com.example.administrator.testdemo D/tag: emit two05-21 06:03:16.205 19473-19503/com.example.administrator.testdemo D/tag: emit 205-21 06:03:16.205 19473-19503/com.example.administrator.testdemo D/tag: onNext :2 = two05-21 06:03:16.306 19473-19504/com.example.administrator.testdemo D/tag: emit three05-21 06:03:16.307 19473-19503/com.example.administrator.testdemo D/tag: emit 305-21 06:03:16.307 19473-19503/com.example.administrator.testdemo D/tag: onNext :3 = three05-21 06:03:16.408 19473-19504/com.example.administrator.testdemo D/tag: emit complete205-21 06:03:16.408 19473-19503/com.example.administrator.testdemo D/tag: emit 405-21 06:03:16.408 19473-19504/com.example.administrator.testdemo D/tag: onComplete
注意:
1、发送的2组事件都需要处于子线程,并且每发送一个事件之后加入一定时间的延时,不然会出现以下的结果:
05-21 06:09:27.572 25819-25819/com.example.administrator.testdemo D/tag: onSubscribe05-21 06:09:27.576 25819-25849/com.example.administrator.testdemo D/tag: emit 105-21 06:09:27.576 25819-25849/com.example.administrator.testdemo D/tag: emit 205-21 06:09:27.576 25819-25849/com.example.administrator.testdemo D/tag: emit 305-21 06:09:27.576 25819-25849/com.example.administrator.testdemo D/tag: emit 405-21 06:09:27.577 25819-25849/com.example.administrator.testdemo D/tag: emit complete105-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: emit one05-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: onNext :1 = one05-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: emit two05-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: onNext :2 = two05-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: emit three05-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: onNext :3 = three05-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: emit complete205-21 06:09:27.578 25819-25850/com.example.administrator.testdemo D/tag: onComplete
2、下游收到的事件数量是和上游中发送事件最少的那一根水管的事件数量相同
思维延伸
我们说到Zip可以将多个上游发送的事件组合起来发送给下游, 那大家有没有想过一个问题, 如果其中一个水管A发送事件特别快, 而另一个水管B 发送事件特别慢的情况,那么会发生什么情况呢…
请看代码:
Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> e) throws Exception { for (int i = 0; ; i++) { //无限循环 e.onNext(i); } } }).subscribeOn(Schedulers.newThread());Observable<String> observable2 = Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { Log.d(TAG, "emit one"); }}).subscribeOn(Schedulers.newThread());Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() { @Override public String apply(Integer integer, String s) throws Exception { return integer + " = " + s; }}).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<String>() { @Override public void accept(String s) throws Exception { Log.d(TAG, "accept:" + s); } });
请看效果:
我的天,翻车了:使用的内存在短时间内急剧上涨,瞬间OOM。
那是不是只有zip会这样,我们一起来看下最简单的:
Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> e) throws Exception { for (int i = 0; ; i++) { //无限循环 e.onNext(i); } }}).subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.d(TAG, "accept:" + integer); } });
跟上面的例子一样,内存也是爆掉了。
上游的每一个事件,下游都要一一处理,而且上游在短时间发送太多的事件,让下游来不及处理就造成了事件的阻塞,那么我们是否可以用一些自己的方法来解决这种阻塞呢?
首先,我们分析阻塞形成的原因,无非是因为下面的原因啊:
- 上游的水流过快(上游发送事件过快)
- 上游水流量过大(上游发送事件过多)
好吧,首先我们用第一种办法试下,让上游发送事件的速度慢点
//控制发送速度,减少内存消耗Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> e) throws Exception { for (int i = 0; ; i++) { //无限循环 e.onNext(i); Thread.sleep(1000); } }}).subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.d(TAG, "accept:" + integer); } });
方案一,成功!
那么,试试第二种方法,下游少接收点事件:
//下游少接收点事件Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> e) throws Exception { for (int i = 0; ; i++) { //无限循环 e.onNext(i); } }}).filter(new Predicate<Integer>() { @Override public boolean test(Integer integer) throws Exception { return integer%100==0; }}).subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.d(TAG, "accept:" + integer); } });
内存上看起来还不错,但是CPU的使用率很恐怖。
上面唠唠叨叨说了那么多,基本上也给大家阐明了阻塞形成的原因和解决阻塞的方法,基本策略就是减少发送事件的频率和减少发送事件的数量。
But…
我们手动让上游发送事件的速度满下来貌似是不可取的,你想让上游的速度十多快呢?上游需要等多久呢?
And…
我们依旧无法知道下游处理事件的能力,无法很好地处理阻塞的事件。
So….
官方是怎样解决的呢?
期待我们下次再见,将带来Flowable的学习,see u :)
- RxJava1.x从入门到放弃再到RxJava 2.x(四)
- RxJava1.x从入门到放弃再到RxJava 2.x(一)
- RxJava1.x从入门到放弃再到RxJava 2.x(二)
- RxJava1.x从入门到放弃再到RxJava 2.x(三)
- 从RxJava1.x到2.0
- JavaScript从入门到放弃(四)
- RxJava 从入门到放弃再到不离不弃
- RxJava1.X升级到RxJava2.X笔记
- RxJava1.X升级到RxJava2.X笔记
- RxJava从入门到放弃---关于RxJava-入门必看
- RxJava从入门到放弃1.0--rxjava的简单使用
- Unity3D 从入门到放弃(四)----打飞碟
- 微信小程序从入门到放弃(四)
- Dagger2+MVP+RxJava+Retrofit从放弃到入门
- android之RxJava的学习,从浅到深,从入门到别放弃(一)
- android之RxJava的学习,从浅到深,从入门到别放弃(二)
- 2. RxJava1.x基本概念
- Android RxJava 2.x入门例子详解(四)
- (62)组件之静态网格模型组件
- Golang unsafe的妙用
- 基于opengl的游戏引擎
- Deep Learning 最优化方法之Momentum(动量)
- 算法设计与结构基础作业第十三周
- RxJava1.x从入门到放弃再到RxJava 2.x(四)
- 循环链表
- 【Redis】Windows安装
- (63)组件之实用工具组件
- webservice开发
- 基于信号处理的在线云评测+社区系统( 4)
- 多线程同步的方法5种
- 1
- pandas DataFrame数据转为list