- 1、创建被观察者过程
- 2、订阅过程
1、创建被观察者过程
首先,上面使用了Observable类的create()方法创建了一个被观察者,看看里面做了什么。
1.1、Observable#create()
// 省略一些检测性的注解
public static Observable create(ObservableOnSubscribe source) {
ObjectHelper.requireNonNull(source, “source is null”);
return RxJavaPlugins.onAssembly(new ObservableCreate(source));
}
在Observable的create()里面实际上是创建了一个新的ObservableCreate对象,同时,把我们定义好的ObservableOnSubscribe对象传入了ObservableCreate对象中,最后调用了RxJavaPlugins.onAssembly()方法。接下来看看这个ObservableCreate是干什么的。
1.2、ObservableCreate
public final class ObservableCreate extends Observable {
final ObservableOnSubscribe source;
public ObservableCreate(ObservableOnSubscribe source) {
this.source = source;
}
…
}
这里仅仅是把ObservableOnSubscribe这个对象保存在ObservableCreate中了。然后看看RxJavaPlugins.onAssembly()这个方法的处理。
1.3、RxJavaPlugins#onAssembly()
public static Observable onAssembly(@NonNull Observable source) {
// 应用hook函数的一些处理,一般用到不到
…
return source;
}
最终仅仅是把我们的ObservableCreate给返回了。
1.4、创建被观察者过程小结
从以上分析可知,Observable.create()方法仅仅是先将我们自定义的ObservableOnSubscribe对象重新包装成了一个ObservableCreate对象。
2、订阅过程
接着,看看Observable.subscribe()的订阅过程是如何实现的。
2.1、Observable#subscribe()
public final void subscribe(Observer<? super T> observer) {
…
// 1
observer = RxJavaPlugins.onSubscribe(this,observer);
…
// 2
subscribeActual(observer);
…
}
在注释1处,在Observable的subscribe()方法内部首先调用了RxJavaPlugins的onSubscribe()方法。
2.2、RxJavaPlugins#onSubscribe()
public static Observer<? super T> onSubscribe(@NonNull Observable source, @NonNull Observer<? super T> observer) {
// 应用hook函数的一些处理,一般用到不到
…
return observer;
}
除去hook应用的逻辑,这里仅仅是将observer返回了。接着来分析下注释2处的subscribeActual()方法,
2.3、Observable#subscribeActual()
protected abstract void subscribeActual(Observer<? super T> observer);
这是一个抽象的方法,很明显,它对应的具体实现类就是我们在第一步创建的ObservableCreate类,接下来看到ObservableCreate的subscribeActual()方法。
2.4、ObservableCreate#subscribeActual()
@Override
protected void subscribeActual(Observer<? super T> observer) {
// 1
CreateEmitter parent = new CreateEmitter(observer);
// 2
observer.onSubscribe(parent);
try {
// 3
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
在注释1处,首先新创建了一个CreateEmitter对象,同时传入了我们自定义的observer对象进去。
2.4.1、CreateEmitter
static final class CreateEmitter
extends AtomicReference
implements ObservableEmitter, Disposable {
…
final Observer<? super T> observer;
CreateEmitter(Observer<? super T> observer) {
this.observer = observer;
}
…
}
从上面可以看出,CreateEmitter通过继承了Java并发包中的原子引用类AtomicReference保证了事件流切断状态Dispose的一致性(这里不理解的话,看到后面讲解Dispose的时候就明白了),并实现了ObservableEmitter接口和Disposable接口,接着我们分析下注释2处的observer.onSubscribe(parent),这个onSubscribe回调的含义其实就是告诉观察者已经成功订阅了被观察者。再看到注释3处的source.subscribe(parent)这行代码,这里的source其实是ObservableOnSubscribe对象,我们看到ObservableOnSubscribe的subscribe()方法。
2.4.2、ObservableOnSubscribe#subscribe()
Observable observable = Observable.create(new ObservableOnSubscribe() {
@Override
public voidsubscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext(“1”);
emitter.onNext(“2”);
emitter.onNext(“3”);
emitter.onComplete();
}
});
这里面使用到了ObservableEmitter的onNext()方法将事件流发送出去,最后调用了onComplete()方法完成了订阅过程。ObservableEmitter是一个抽象类,实现类就是我们传入的CreateEmitter对象,接下来我们看看CreateEmitter的onNext()方法和onComplete()方法的处理。
2.4.3、CreateEmitter#onNext() && CreateEmitter#onComplete()
static final class CreateEmitter
extends AtomicReference
implements ObservableEmitter, Disposable {
…
@Override
public void onNext(T t) {
…
if (!isDisposed()) {
//调用观察者的onNext()
observer.onNext(t);
}
}
@Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
dispose();
}
}
}
…
}
在CreateEmitter的onNext和onComplete方法中首先都要经过一个isDisposed的判断,作用就是看当前的事件流是否被切断(废弃)掉了,默认是不切断的,如果想要切断,可以调用Disposable的dispose()方法将此状态设置为切断(废弃)状态。我们继续看看这个isDisposed内部的处理。
2.4.4、ObservableEmitter#isDisposed()
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
注意到这里通过get()方法首先从ObservableEmitter的AtomicReference中拿到了保存的Disposable状态。然后交给了DisposableHelper进行判断处理。接下来看看DisposableHelper的处理。
2.4.5、DisposableHelper#isDisposed() && DisposableHelper#set()
public enum DisposableHelper implements Disposable {
DISPOSED;
public static boolean isDisposed(Disposable d) {
// 1
return d == DISPOSED;
}
public static boolean set(AtomicReference field, Disposable d) {
for (;😉 {
Disposable current = field.get();
if (current == DISPOSED) {
if (d != null) {
d.dispose();
}
return false;
}
// 2
if (field.compareAndSet(current, d)) {
if (current != null) {
current.dispose();
}
return true;
}
}
}
…
public static boolean dispose(AtomicReference field) {
Disposable current = field.get();
Disposable d = DISPOSED;
if (current != d) {
// …
current = field.getAndSet(d);
if (current != d) {
if (current != null) {
current.dispose();
}
return true;
}
}
return false;
}
…
}
DisposableHelper是一个枚举类,内部只有一个值即DISPOSED, 从上面的分析可知它就是用来标记事件流被切断(废弃)状态的。先看到注释2和注释3处的代码field.compareAndSet(current, d)和field.getAndSet(d),这里使用了原子引用AtomicReference内部包装的CAS方法处理了标志Disposable的并发读写问题。最后看到注释3处,将我们传入的CreateEmitter这个原子引用类保存的Dispable状态和DisposableHelper内部的DISPOSED进行比较,如果相等,就证明数据流被切断了。为了更进一步理解Disposed的作用,再来看看CreateEmitter中剩余的关键方法。
2.4.6、CreateEmitter
@Override
public void onNext(T t) {
…
// 1
if (!isDisposed()) {
observer.onNext(t);
}
}
@Override
public void onError(Throwable t) {
if (!tryOnError(t)) {
// 2
RxJavaPlugins.onError(t);
}
}
@Override
public boolean tryOnError(Throwable t) {
…
// 3
if (!isDisposed()) {
try {
observer.onError(t);
} finally {
// 4
dispose();
}
return true;
}
return false;
}
@Override
public void onComplete() {
// 5
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
// 6
dispose();
}
}
}
在注释1、3、5处,onNext()和onError()、onComplete()方法首先都会判断事件流是否被切断,如果事件流此时被切断了,那么onNext()和onComplete()则会退出方法体,不做处理,onError()则会执行到RxJavaPlugins.onError(t)这句代码,内部会直接抛出异常,导致崩溃。如果事件流没有被切断,那么在onError()和onComplete()内部最终会调用到注释4、6处的这句dispose()代码,将事件流进行切断,由此可知,onError()和onComplete()只能调用一个,如果先执行的是onComplete(),再调用onError()的话就会导致异常崩溃。
三、RxJava的线程切换
首先给出RxJava线程切换的例子:
Observable.create(new ObservableOnSubscribe() {
@Override
public voidsubscribe(ObservableEmitteremitter) throws Exception {
emitter.onNext(“1”);
emitter.onNext(“2”);
emitter.onNext(“3”);
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, “onSubscribe”);
}
@Override
public void onNext(String s) {
Log.d(TAG, "onNext : " + s);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError : " +e.toString());
}
@Override
public void onComplete() {
Log.d(TAG, “onComplete”);
}
});
可以看到,RxJava的线程切换主要分为subscribeOn()和observeOn()方法,首先,来分析下subscribeOn()方法。
1、subscribeOn(Schedulers.io())
在Schedulers.io()方法中,我们需要先传入一个Scheduler调度类,这里是传入了一个调度到io子线程的调度类,我们看看这个Schedulers.io()方法内部是怎么构造这个调度器的。
2、Schedulers#io()
static final Scheduler IO;
…
public static Scheduler io() {
// 1
return RxJavaPlugins.onIoScheduler(IO);
}
static {
…
// 2
IO = RxJavaPlugins.initIoScheduler(new IOTask());
}
static final class IOTask implements Callable {
@Override
public Scheduler call() throws Exception {
// 3
return IoHolder.DEFAULT;
}
}
static final class IoHolder {
// 4
static final Scheduler DEFAULT = new IoScheduler();
}
Schedulers这个类的代码很多,这里我只拿出有关Schedulers.io这个方法涉及的逻辑代码进行讲解。首先,在注释1处,同前面分析的订阅流程的处理一样,只是一个处理hook的逻辑,最终返回的还是传入的这个IO对象。再看到注释2处,在Schedulers的静态代码块中将IO对象进行了初始化,其实质就是新建了一个IOTask的静态内部类,在IOTask的call方法中,也就是注释3处,可以了解到使用了静态内部类的方式把创建的IOScheduler对象给返回出去了。绕了这么大圈子,Schedulers.io方法其实质就是返回了一个IOScheduler对象。
3、Observable#subscribeOn()
public final Observable subscribeOn(Scheduler scheduler) {
…
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn(this, scheduler));
}
在subscribeOn()方法里面,又将ObservableCreate包装成了一个ObservableSubscribeOn对象。我们关注到ObservableSubscribeOn类。
4、ObservableSubscribeOn
public final class ObservableSubscribeOn extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
public ObservableSubscribeOn(ObservableSource source, Scheduler scheduler) {
// 1
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> observer) {
// 2
final SubscribeOnObserver parent = new SubscribeOnObserver(observer);
// 3
observer.onSubscribe(parent);
// 4
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
…
}
首先,在注释1处,将传进来的source和scheduler保存起来。接着,等到实际订阅的时候,就会执行到这个subscribeActual方法,在注释2处,将我们自定义的Observer包装成了一个SubscribeOnObserver对象。在注释3处,通知观察者订阅了被观察者。在注释4处,内部先创建了一个SubscribeTask对象,来看看它的实现。
5、ObservableSubscribeOn#SubscribeTask
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver parent;
SubscribeTask(SubscribeOnObserver parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
SubscribeTask是ObservableSubscribeOn的内部类,它实质上就是一个任务类,在它的run方法中会执行到source.subscribe(parent)的订阅方法,这个source其实就是我们在ObservableSubscribeOn构造方法中传进来的ObservableCreate对象。接下来看看scheduler.scheduleDirect()内部的处理。
6、Scheduler#scheduleDirect()
public Disposable scheduleDirect(@NonNull Runnable run) {
return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
}
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
// 1
final Worker w = createWorker();
// 2
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
// 3
DisposeTask task = new DisposeTask(decoratedRun, w);
// 4
w.schedule(task, delay, unit);
return task;
}
这里最后会执行到上面这个scheduleDirect()重载方法。首先,在注释1处,会调用createWorker()方法创建一个工作者对象Worker,它是一个抽象类,这里的实现类就是IoScheduler,下面,我们看看IoScheduler类的createWorker()方法。
6.1、IOScheduler#createWorker()
final AtomicReference pool;
…
public IoScheduler(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
this.pool = new AtomicReference(NONE);
start();
}
…
@Override
public Worker createWorker() {
// 1
return new EventLoopWorker(pool.get());
}
static final class EventLoopWorker extends Scheduler.Worker {
…
EventLoopWorker(CachedWorkerPool pool) {
this.pool = pool;
this.tasks = new CompositeDisposable();
// 2
this.threadWorker = pool.get();
}
}
首先,在注释1处调用了pool.get()这个方法,pool是一个CachedWorkerPool类型的原子引用对象,它的作用就是用于缓存工作者对象Worker的。然后,将得到的CachedWorkerPool传入新创建的EventLoopWorker对象中。重点关注一下注释2处,这里将CachedWorkerPool缓存的threadWorker对象保存起来了。
下面,我们继续分析3.6处代码段的注释2处的代码,这里又是一个关于hook的封装处理,最终还是返回的当前的Runnable对象。在注释3处新建了一个切断任务DisposeTask将decoratedRun和w对象包装了起来。最后在注释4处调用了工作者的schedule()方法。下面我们来分析下它内部的处理。
6.2、IoScheduler#schedule()
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
总结
其实要轻松掌握很简单,要点就两个:
- 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
- 多练。 (视频优势是互动感强,容易集中注意力)
你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
非常高的。**
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-cAIlienf-1713787670369)]
这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!