這篇文章來總結一下Rxjava中切換執行緒的內在是怎麼實現的
ObservableOn()
直接檢視實現,會發現onSubscribe()
中做了一些判斷,比如82
104
等幾行都是做了一些同步
非同步
等的判斷,然後初始化Disposable
,onSubscribe()
是上游Observable
完成了整條訂閱鏈之後呼叫的,所以這些操作是在開始訂閱之後才初始化操作,然後106
行可以看出把一個包裝處理過的Disposable
傳遞給下游
和之前的一樣,subscribeActual
方法裡會將observer
進行包裝,然後傳遞給source也就是上游進行訂閱
* `40`行進行了判斷所傳進來的`scheduler`是否跟原本的執行緒一致,如果是一樣的就直接傳遞不用進行處理
* `43`行建立了一個對應`scheduler`的`worker`,`worker`在後續負責把資料在對應的執行緒進行發射操作
複製程式碼
發射資料onNext
處理
@Override
public void onNext(T t) {
...
// 前面的都先忽略掉,會發現最後會呼叫這個方法
schedule();
}
void schedule() {
if (getAndIncrement() == 0) {
// 在這個可以看到,上面根據schedule的worker執行了schedule(),並且把自身傳進去,this其實實現了runnable,所以可以理解為傳了一個runnable進去
worker.schedule(this);
}
}
複製程式碼
接著上面的以AndroidSchedulers.mainThread()
這個scheduler為例,這裡實際上是將主執行緒的looper
傳進去了
檢視一下這個scheduler的worker,會發現worker的基類schedule()方法是相同的互相呼叫的,所以可以直接看多個引數的schedule(),可以看到73
行建立了一個ScheduledRunnable
物件,並且把主執行緒的handler
以及外面的Observer
傳遞過去,接著82
行用主執行緒的handler傳送訊息,119
行ScheduledRunnable
裡的run
被呼叫,接著Observer也就是runnable
也呼叫run
方法
到這裡可以看出,實際上當切換執行緒的時候,observer(也實現了Runnable
)的onNext往scheduler裡傳送自身,讓scheduler來決定自身應該在什麼執行緒執行run方法,接下來看回observer的run方法,就是判斷了一下要執行哪個方法
可以看到最後是呼叫了onNext方法,到這裡就完成了指定執行緒發射資料的功能
void drainNormal() {
int missed = 1;
final SimpleQueue<T> q = queue;
final Observer<? super T> a = downstream;
for (;;) {
if (checkTerminated(done, q.isEmpty(), a)) {
return;
}
for (;;) {
boolean d = done;
T v;
try {
v = q.poll();
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
disposed = true;
upstream.dispose();
q.clear();
a.onError(ex);
worker.dispose();
return;
}
boolean empty = v == null;
if (checkTerminated(d, empty, a)) {
return;
}
if (empty) {
break;
}
a.onNext(v);
}
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
複製程式碼
值得注意的是可以看到的是v
也就是我們要發射的資料,是通過poll
方法獲取的,檢視程式碼可以發現
queue
實際上就是一個Disposable
也就是說是上游Observable
,通過上游的poll方法去獲取要onNext的資料
檢視Observable
其中一個實現ObservableMap
的poll方法,可以看到這裡實際上也是呼叫上游的poll方法,並且對資料的格式也就是不允許為null做了一層判斷
public U poll() throws Exception {
T t = qd.poll();
return t != null ? ObjectHelper.<U>requireNonNull(mapper.apply(t), "The mapper function returned a null value.") : null;
}
複製程式碼
poll方法操作的物件實際上是下圖104
行的時候new出來的,具體檢視其實就是快取資料,類似一個容量池的作用
用一段虛擬碼來展示切換執行緒之後的observer,其實相當於onNext等方法都被放在指定的執行緒裡去發射資料
public class Observer {
Observer oldObserver;
public Observer(Observer observer) {
oldObserver = observer;
}
public void onNext(T t) {
// 一些其他操作
new Thread("Android mainThread") {
@Override
public void run() {
oldObserver.onNext(t);
}
} .start();
}
public void onError(Throwable e) {
// 一些其他操作
new Thread("Android mainThread") {
@Override
public void run() {
oldObserver.onError(e);
}
} .start();
}
public void onComplete() {
// 一些其他操作
new Thread("Android mainThread") {
@Override
public void run() {
oldObserver.onComplete();
}
} .start();
}
}
複製程式碼