RxJava源码解析(三,2021最新Android面试真题解析

2021年09月15日 阅读数:1
这篇文章主要向大家介绍RxJava源码解析(三,2021最新Android面试真题解析,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。
                       callError = true;
                      break;
                 }
    } else {
                 dq.offer(t);
      }

}
if (callOnOverflow) {
if (onOverflow != null) {
try {
onOverflow.run();
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
s.cancel();
onError(ex);
}
}
} else if (callError) {
s.cancel();
onError(new MissingBackpressureException());
} else {
drain();
}
}
...
}android

在这段源码中,根据不一样的背压策略进行了不一样的处理措施,固然这只是列举了一段关于buffer背压策略的例子。
#### 根源
产生背压问题的根源就是上游发送速度与下游的处理速度不均致使的,因此若是想要解决这个问题就须要经过匹配两个速率达到解决这个背压根源的措施。
**一般有两个策略可供使用:**
> 1. 从数量上解决,对数据进行采样
> 2. 从速度上解决,下降发送事件的速率
> 3. 利用flowable和subscriber

#### 使用Flowable

Flowable<Integer> upstream = Flowable.create(new FlowableOnSubscribe<Integer>() {br/>@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
Log.d(TAG, "emit 1");
emitter.onNext(1);
Log.d(TAG, "emit 2");
emitter.onNext(2);
Log.d(TAG, "emit 3");
emitter.onNext(3);
Log.d(TAG, "emit complete");
emitter.onComplete();
}
}, BackpressureStrategy.ERROR); //增长了一个参数
Subscriber<Integer> downstream = new Subscriber<Integer>() {br/>@Override
public void onSubscribe(Subscription s) {
Log.d(TAG, "onSubscribe");
s.request(Long.MAX_VALUE); //注意这句代码
}git

    @Override
    public void onNext(Integer integer) {
          Log.d(TAG, "onNext: " + integer);
    }
    @Override
    public void onError(Throwable t) {
          Log.w(TAG, "onError: ", t);
    }
    @Override
     public void onComplete() {
           Log.d(TAG, "onComplete");
     }

};
upstream.subscribe(downstream);面试

咱们注意到此次和 Observable 有些不一样. 首先是建立 Flowable 的时候增长了一个参数, 这个参数是用来选择背压,也就是出现上下游流速不均衡的时候应该怎么处理的办法, 这里咱们直接用 `BackpressureStrategy.ERROR` 这种方式,这种方式会在出现上下游流速不均衡的时候直接抛出一个异常,这个异常就是著名的`MissingBackpressureException` . 其他的策略后面再来说解.

另外的一个区别是在下游的 `onSubscribe` 方法中传给咱们的再也不是 Disposable 了, 而是 `Subscription` , 它俩有什么区别呢, 首先它们都是上下游中间的一个开关, 以前咱们说调用 `Disposable.dispose()` 方法能够切断水管, 一样的调用 `Subscription.cancel()` 也能够切断水管, 不一样的地方在于 `Subscription`增长了一个 `void request(longn)` 方法, 这个方法有什么用呢, 在上面的代码中也有这么一句代码:

s.request(Long.MAX_VALUE);缓存

这是由于 `Flowable` 在设计的时候采用了一种新的思路也就是 响应式拉取 的方式来更好的解决上下游流速不均衡的问题, 与咱们以前所讲的 控制数量 和 控制速度 不太同样, 这种方式用通俗易懂的话来讲就比如是 叶问打鬼子 , 咱们把 上游当作 小日本 , 把 下游 看成 叶问 , 当调用 `Subscription.request(1)` 时,  叶问 就说 我要打一个! 而后 小日本 就拿出 一个鬼子 给叶问, 让他打, 等叶问打死这个鬼子以后, 再次调用 `request(10)` , 叶问就又说 我要打十个! 而后小日本又派出 十个鬼子 给叶问, 而后就在边上看热闹, 看叶问能不能打死十个鬼子, 等叶问打死十个鬼子后再继续要鬼子接着打...

因此咱们把request当作是一种能力, 当成 下游处理事件 的能力, 下游能处理几个就告诉上游我要几个, 这样只要上游根据下游的处理能力来决定发送多少事件, 就不会形成一窝蜂的发出一堆事件来, 从而致使`OOM`. 这也就完美的解决以前咱们所学到的两种方式的缺陷, 过滤事件会致使事件丢失, 减速又可能致使性能损失. 而这种方式既解决了事件丢失的问题, 又解决了速度的问题, 完美 !

#### 同步状况

Observable.create(new ObservableOnSubscribe<Integer>() {br/>@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
for (int i = 0; ; i++) { //无限循环发事件
emitter.onNext(i);
}
}
}).subscribe(new Consumer<Integer>() {br/>@Override
public void accept(Integer integer) throws Exception {
Thread.sleep(2000);
Log.d(TAG, "" + integer);
}
});markdown

当上下游工做在 同一个线程 中时, 这时候是一个 同步 的订阅关系, 也就是说 上游 每发送一个事件 必须 等到 下游 接收处理完了之后才能接着发送下一个事件.

同步与异步的区别就在于有没有缓存发送事件的缓冲区。
#### 异步状况
经过`subscribeOn`和`observeOn`来肯定对应的线程,达到异步的效果,异步时会有一个对应的缓存区来换从从上游发送的事件。

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
    }
    
    **背压策略:**
    > 1. error, 缓冲区大概在128
    > 2. buffer, 缓冲区在1000左右
    > 3. drop, 把存不下的事件丢弃
    > 4. latest, 只保留最新的
    > 5. missing, 缺省设置,不作任何操做

上游从哪里得知下游的处理能力呢?咱们来看看上游最重要的部分,确定就是 FlowableEmitter 了啊,咱们就是经过它来发送事件的啊,来看看它的源码吧(别紧张,它的代码灰常简单):app


  public interface FlowableEmitter<T> extends Emitter<T> {
      void setDisposable(Disposable s);
## 最后

说一千道一万,不如本身去行动。要想在移动互联网的下半场是本身占有一席之地,那就得从如今开始,从今天开始,立刻严格要求本身,**既重视业务实现能力,也重视基础和原理。基础夯实好了,高楼才可以平地而起,稳如泰山。**

最后为了帮助你们深入理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套**腾讯、字节跳动、阿里、百度2020-2021面试真题解析**,我把技术点整理成了**视频和PDF**(实际上比预期多花了很多精力),包**知识脉络 + 诸多细节**。

还有?**高级架构技术进阶脑图、Android开发面试专题资料**?帮助你们学习提高进阶,也节省你们在网上搜索资料的时间来学习,也能够分享给身边好友一块儿学习。

![一线互联网面试专题](https://s2.51cto.com/images/20210903/1630664069232211.jpg)

![379页的Android进阶知识大全](https://s2.51cto.com/images/20210903/1630664069622399.jpg)

![379页的Android进阶知识大全](https://s2.51cto.com/images/20210903/1630664069179376.jpg)

**点击:**

**《[Android架构视频+BAT面试专题PDF+学习笔记](https://gitee.com/vip204888/android-p7)?》**

便可免费获取~

网上学习 Android的资料一大堆,但若是学到的知识不成体系,遇到问题时只是浅尝辄止,再也不深刻研究,那么很难作到真正的技术提高。但愿这份系统化的技术体系对你们有一个方向参考。