RxJava2 源码解析(二),2024年最新阿里二面面试官级别

public final Observable subscribeOn(Scheduler scheduler) {

//判空略过

ObjectHelper.requireNonNull(scheduler, “scheduler is null”);

//抛开Hook,重点还是ObservableSubscribeOn

return RxJavaPlugins.onAssembly(new ObservableSubscribeOn(this, scheduler));

}

等等,怎么有种似曾相识的感觉,大家可以把文章向上翻,看看map()的源码。

subscribeOn()的套路如出一辙,那么我们根据上面的结论,

先猜测**ObservableSubscribeOn类也是一个包装类(装饰者)**,点进去查看:

public final class ObservableSubscribeOn extends AbstractObservableWithUpstream<T, T> {

//保存线程调度器

final Scheduler scheduler;

public ObservableSubscribeOn(ObservableSource source, Scheduler scheduler) {

//map的源码中我们分析过,super()只是简单的保存ObservableSource

super(source);

this.scheduler = scheduler;

}

@Override

public void subscribeActual(final Observer<? super T> s) {

//1 创建一个包装Observer

final SubscribeOnObserver parent = new SubscribeOnObserver(s);

//2 手动调用 下游(终点)Observer.onSubscribe()方法,所以onSubscribe()方法执行在 订阅处所在的线程

s.onSubscribe(parent);

//3 setDisposable()是为了将子线程的操作加入Disposable管理中

parent.setDisposable(scheduler.scheduleDirect(new Runnable() {

@Override

public void run() {

//4 此时已经运行在相应的Scheduler 的线程中

source.subscribe(parent);

}

}));

}

和map套路大体一致,ObservableSubscribeOn自身同样是个包装类,同样继承AbstractObservableWithUpstream

创建了一个SubscribeOnObserver类,该类按照套路,应该也是实现了ObserverDisposable接口的包装类,让我们看一下:

static final class SubscribeOnObserver extends AtomicReference implements Observer, Disposable {

//真正的下游(终点)观察者

final Observer<? super T> actual;

//用于保存上游的Disposable,以便在自身dispose时,连同上游一起dispose

final AtomicReference s;

SubscribeOnObserver(Observer<? super T> actual) {

this.actual = actual;

this.s = new AtomicReference();

}

@Override

public void onSubscribe(Disposable s) {

//onSubscribe()方法由上游调用,传入Disposable。在本类中赋值给this.s,加入管理。

DisposableHelper.setOnce(this.s, s);

}

//直接调用下游观察者的对应方法

@Override

public void onNext(T t) {

actual.onNext(t);

}

@Override

public void onError(Throwable t) {

actual.onError(t);

}

@Override

public void onComplete() {

actual.onComplete();

}

//取消订阅时,连同上游Disposable一起取消

@Override

public void dispose() {

DisposableHelper.dispose(s);

DisposableHelper.dispose(this);

}

@Override

public boolean isDisposed() {

return DisposableHelper.isDisposed(get());

}

//这个方法在subscribeActual()中被手动调用,为了将Schedulers返回的Worker加入管理

void setDisposable(Disposable d) {

DisposableHelper.setOnce(this, d);

}

}

这两个类根据上一节的铺垫加上注释,其他都好理解,稍微不好理解的应该是下面两句代码:

//ObservableSubscribeOn类

//3 setDisposable()是为了将子线程的操作加入Disposable管理中

parent.setDisposable(scheduler.scheduleDirect(new Runnable() {

@Override

public void run() {

//4 此时已经运行在相应的Scheduler 的线程中

source.subscribe(parent);

}

}));

//SubscribeOnObserver类

//这个方法在subscribeActual()中被手动调用,为了将Schedulers返回的Worker加入管理

void setDisposable(Disposable d) {

DisposableHelper.setOnce(this, d);

}

其中scheduler.scheduleDirect(new Runnable()..)方法源码如下:

/**

  • Schedules the given task on this scheduler non-delayed execution.

*/

public Disposable scheduleDirect(Runnable run) {

return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);

}

从注释和方法名我们可以看出,这个传入的Runnable会立刻执行

再继续往里面看:

public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) {

//class Worker implements Disposable ,Worker本身是实现了Disposable

final Worker w = createWorker();

//hook略过

final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

//开始在Worker的线程执行任务,

w.schedule(new Runnable() {

@Override

public void run() {

try {

//调用的是 run()不是 start()方法执行的线程的方法。

decoratedRun.run();

} finally {

//执行完毕会 dispose()

w.dispose();

}

}

}, delay, unit);

//返回Worker对象

return w;

}

createWorker()是一个抽象方法,由具体的Scheduler类实现,例如IoScheduler对应的Schedulers.io().

public abstract Worker createWorker();

初看源码,为了了解大致流程,不宜过入深入,先点到为止。

OK,现在我们总结一下scheduler.scheduleDirect(new Runnable()..)的重点:

  1. 传入的Runnable立刻执行的。

  2. 返回的**Worker对象就是一个Disposable对象**,

  3. Runnable执行时,是直接手动调用的 run(),而不是 start()方法.

  4. 上一点应该是为了,能控制在run()结束后(包括异常终止),都会自动执行Worker.dispose().

而返回的**Worker对象**也会被parent.setDisposable(...)加入管理中,以便在手动dispose()时能取消线程里的工作。

我们总结一下subscribeOn(Schedulers.xxx())过程

  1. 返回一个ObservableSubscribeOn包装类对象

  2. 上一步返回的对象被订阅时,回调该类中的subscribeActual()方法,在其中会立刻将线程切换到对应的Schedulers.xxx()线程。

  3. 在切换后的线程中,执行source.subscribe(parent);对上游(终点)Observable订阅

  4. 上游(终点)Observable开始发送数据,根据RxJava2 源码解析(一),上游发送数据仅仅是调用下游观察者对应的onXXX()方法而已,所以此时操作是在切换后的线程中进行


一点扩展,

大家可能看过一个结论:

subscribeOn(Schedulers.xxx())切换线程N次,总是以第一次为准,或者说离源Observable最近的那次为准,并且对其上面的代码生效(这一点对比的ObserveOn())。

为什么?

- 因为根据RxJava2 源码解析(一)中提到,订阅流程从下游往上游传递

- 在subscribeActual()里开启了Scheduler的工作,source.subscribe(parent);,从这一句开始切换了线程,所以在这之上的代码都是在切换后的线程里的了。

- 但如果连续切换最上面的切换最晚执行,此时线程变成了最上面的subscribeOn(xxxx)指定的线程,

- 而数据push时,是从上游到下游的,所以会在离源头最近的那次subscribeOn(xxxx)的线程里push数据(onXXX())给下游。

可写如下代码验证:

Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter e) throws Exception {

Log.d(TAG, “subscribe() called with: e = [” + e + “]” + Thread.currentThread());

e.onNext(“1”);

e.onComplete();

}

}).subscribeOn(Schedulers.io())

.map(new Function<String, String>() {

@Override

public String apply(String s) throws Exception {

//依然是io线程

Log.d(TAG, “apply() called with: s = [” + s + “]” + Thread.currentThread());

return s;

}

})

.subscribeOn(Schedulers.computation())

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, “onSubscribe() called with: d = [” + d + “]”);

}

@Override

public void onNext(String value) {

Log.d(TAG, “onNext() called with: value = [” + value + “]”);

}

@Override

public void onError(Throwable e) {

Log.d(TAG, “onError() called with: e = [” + e + “]”);

}

@Override

public void onComplete() {

Log.d(TAG, “onComplete() called”);

}

});

线程调度observeOn


在上一节的基础上,增加一个observeOn(AndroidSchedulers.mainThread()),就完成了观察者线程的切换。

.subscribeOn(Schedulers.computation())

//在上一节的基础上,增加一个ObserveOn

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer() {

继续看源码吧,我已经能猜出来了,hook+new XXXObservable();

public final Observable observeOn(Scheduler scheduler) {

return observeOn(scheduler, false, bufferSize());

}

public final Observable observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {

return RxJavaPlugins.onAssembly(new ObservableObserveOn(this, scheduler, delayError, bufferSize));

}

果然,查看ObservableObserveOn,:

高能预警,这部分的代码 有些略多,建议读者打开源码边看边读。

public final class ObservableObserveOn extends AbstractObservableWithUpstream<T, T> {

//本例是 AndroidSchedulers.mainThread()

final Scheduler scheduler;

//默认false

final boolean delayError;

//默认128

final int bufferSize;

public ObservableObserveOn(ObservableSource source, Scheduler scheduler, boolean delayError, int bufferSize) {

super(source);

this.scheduler = scheduler;

this.delayError = delayError;

this.bufferSize = bufferSize;

}

@Override

protected void subscribeActual(Observer<? super T> observer) {

// false

if (scheduler instanceof TrampolineScheduler) {

source.subscribe(observer);

} else {

//1 创建出一个 主线程的Worker

Scheduler.Worker w = scheduler.createWorker();

//2 订阅上游数据源,

source.subscribe(new ObserveOnObserver(observer, w, delayError, bufferSize));

}

}

本例中,就是两步:

  1. 创建一个AndroidSchedulers.mainThread()对应的Worker

  2. ObserveOnObserver订阅上游数据源。这样当数据从上游push下来,会由ObserveOnObserver对应的onXXX()处理。

static final class ObserveOnObserver extends BasicIntQueueDisposable

implements Observer, Runnable {

//下游的观察者

final Observer<? super T> actual;

//对应Scheduler里的Worker

final Scheduler.Worker worker;

//上游被观察者 push 过来的数据都存在这里

SimpleQueue queue;

Disposable s;

//如果onError了,保存对应的异常

Throwable error;

//是否完成

volatile boolean done;

//是否取消

volatile boolean cancelled;

// 代表同步发送 异步发送

int sourceMode;

@Override

public void onSubscribe(Disposable s) {

if (DisposableHelper.validate(this.s, s)) {

this.s = s;

//省略大量无关代码

//创建一个queue 用于保存上游 onNext() push的数据

queue = new SpscLinkedArrayQueue(bufferSize);

//回调下游观察者onSubscribe方法

actual.onSubscribe(this);

}

}

@Override

public void onNext(T t) {

//1 执行过error / complete 会是true

if (done) {

return;

}

//2 如果数据源类型不是异步的, 默认不是

if (sourceMode != QueueDisposable.ASYNC) {

//3 将上游push过来的数据 加入 queue里

queue.offer(t);

}

//4 开始进入对应Workder线程,在线程里 将queue里的t 取出 发送给下游Observer

schedule();

}

@Override

public void onError(Throwable t) {

//已经done 会 抛异常 和 上一篇文章里提到的一样

if (done) {

RxJavaPlugins.onError(t);

return;

}

//给error存个值

error = t;

done = true;

//开始调度

schedule();

}

@Override

public void onComplete() {

//已经done 会 返回 不会crash 和上一篇文章里提到的一样

if (done) {

return;

}

done = true;

//开始调度

schedule();

}

void schedule() {

if (getAndIncrement() == 0) {

//该方法需要传入一个线程, 注意看本类实现了Runnable的接口,所以查看对应的run()方法

worker.schedule(this);

}

}

//从这里开始,这个方法已经是在Workder对应的线程里执行的了

@Override

public void run() {

//默认是false

if (outputFused) {

drainFused();

} else {

//取出queue里的数据 发送

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后

都说三年是程序员的一个坎,能否晋升或者提高自己的核心竞争力,这几年就十分关键。

技术发展的这么快,从哪些方面开始学习,才能达到高级工程师水平,最后进阶到Android架构师/技术专家?我总结了这 5大块;

我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
,可以添加V获取:vip204888 (备注Android)**
[外链图片转存中…(img-2lecAa0p-1712665317096)]

最后

都说三年是程序员的一个坎,能否晋升或者提高自己的核心竞争力,这几年就十分关键。

技术发展的这么快,从哪些方面开始学习,才能达到高级工程师水平,最后进阶到Android架构师/技术专家?我总结了这 5大块;

我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

[外链图片转存中…(img-MLK927ZF-1712665317096)]

[外链图片转存中…(img-fAOCS7BG-1712665317096)]

[外链图片转存中…(img-WkbpsJqQ-1712665317097)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-1adzEOk9-1712665317097)]

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值