rxjava是一個在java虛擬機上的響應式擴展,通過使用可觀察的序列將異步和基于事件的程序組合起來的一個庫。
它擴展了觀察者模式來支持數據/事件序列,并且添加了操作符,這些操作符允許你聲明性地組合序列,同時抽象出要關注的問題:比如低級線程、同步、線程安全和并發數據結構等。
rxjava相信大家都非常了解吧,今天分享一下rxjava的消息發送和線程源碼的分析。最后并分享一個相關demo,讓大家更加熟悉我們天天都在用的框架。
消息訂閱發送
首先讓我們看看消息訂閱發送最基本的代碼組成:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
observable observable = observable.create( new observableonsubscribe<string>() { @override public void subscribe(observableemitter<string> emitter) throws exception { emitter.onnext( "jack1" ); emitter.onnext( "jack2" ); emitter.onnext( "jack3" ); emitter.oncomplete(); } }); observer<string> observer = new observer<string>() { @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" ); } }; observable.subscribe(observer); |
代碼很簡單,observable為被觀察者,observer為觀察者,然后通過observable.subscribe(observer),把觀察者和被觀察者關聯起來。被觀察者發送消息(emitter.onnext("內容")),觀察者就可以在onnext()方法里回調出來。
我們先來看observable,創建是用observable.create()方法進行創建,源碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public static <t> observable<t> create(observableonsubscribe<t> source) { objecthelper.requirenonnull(source, "source is null" ); return rxjavaplugins.onassembly( new observablecreate<t>(source)); } public static <t> t requirenonnull(t object, string message) { if (object == null ) { throw new nullpointerexception(message); } return object; } public static <t> observable<t> onassembly( @nonnull observable<t> source) { function<? super observable, ? extends observable> f = onobservableassembly; if (f != null ) { return apply(f, source); } return source; } |
可以看出,create()方法里最主要的還是創建用observableonsubscribe傳入創建了一個observablecreate對象并且保存而已。
1
2
3
4
5
6
7
8
|
public final class observablecreate<t> extends observable<t> { final observableonsubscribe<t> source; public observablecreate(observableonsubscribe<t> source) { this .source = source; } } |
接著是創建observer,這比較簡單只是單純創建一個接口對象而已
1
2
3
4
5
6
7
8
9
|
public interface observer<t> { void onsubscribe( @nonnull disposable d); void onnext( @nonnull t t); void onerror( @nonnull throwable e); void oncomplete(); } |
訂閱發送消息
observable.subscribe(observer)的subscribe方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public final void subscribe(observer<? super t> observer) { objecthelper.requirenonnull(observer, "observer is null" ); try { observer = rxjavaplugins.onsubscribe( this , observer); objecthelper.requirenonnull(observer, "plugin returned null observer" ); subscribeactual(observer); } catch (nullpointerexception e) { // nopmd throw e; } catch (throwable e) { exceptions.throwiffatal(e); rxjavaplugins.onerror(e); nullpointerexception npe = new nullpointerexception( "actually not, but can't throw other exceptions due to rs" ); npe.initcause(e); throw npe; } } //objecthelper.requirenonnull()方法 public static <t> t requirenonnull(t object, string message) { if (object == null ) { throw new nullpointerexception(message); } return object; } //rxjavaplugins.onsubscribe()方法 public static <t> observer<? super t> onsubscribe( @nonnull observable<t> source, @nonnull observer<? super t> observer) { bifunction<? super observable, ? super observer, ? extends observer> f = onobservablesubscribe; if (f != null ) { return apply(f, source, observer); } return observer; } |
從上面源碼可以看出requirenonnull()只是做非空判斷而已,而rxjavaplugins.onsubscribe()也只是返回最終的觀察者而已。所以關鍵代碼是抽象方法subscribeactual(observer);那么subscribeactual對應哪個代碼段呢?
還記得observable.create()創建的observablecreate類嗎,這就是subscribeactual()具體實現類,源碼如下:
1
2
3
4
5
6
7
8
9
10
|
protected void subscribeactual(observer<? super t> observer) { createemitter<t> parent = new createemitter<t>(observer); observer.onsubscribe(parent); try { source.subscribe(parent); } catch (throwable ex) { exceptions.throwiffatal(ex); parent.onerror(ex); } } |
從上面的代碼可以看出,首先創建了一個createemitter對象并傳入observer,然后回到observer的onsubscribe()方法,而source就是我們之前創建observablecreate傳入的observableonsubscribe對象。
1
2
3
4
|
class createemitter<t> extends atomicreference<disposable> implements observableemitter<t>, disposable { } |
而createemitter又繼承observableemitter接口,又回調observableonsubscribe的subscribe方法,對應著我們的:
1
2
3
4
5
6
7
8
9
|
observable observable = observable.create( new observableonsubscribe<string>() { @override public void subscribe(observableemitter<string> emitter) throws exception { emitter.onnext( "jack1" ); emitter.onnext( "jack2" ); emitter.onnext( "jack3" ); emitter.oncomplete(); } }); |
當它發送消息既調用emitter.onnext()方法時,既調用了createemitter的onnext()方法:
1
2
3
4
5
6
7
8
9
|
public void onnext(t t) { if (t == null ) { onerror( new nullpointerexception( "onnext called with null. null values are generally not allowed in 2.x operators and sources." )); return ; } if (!isdisposed()) { observer.onnext(t); } } |
可以看到最終又回調了觀察者的onnext()方法,把被觀察者的數據傳輸給了觀察者。有人會問
isdisposed()是什么意思,是判斷要不要終止傳遞的,我們看emitter.oncomplete()源碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public void oncomplete() { if (!isdisposed()) { try { observer.oncomplete(); } finally { dispose(); } } } public static boolean dispose(atomicreference<disposable> 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 ; } public static boolean isdisposed(disposable d) { return d == disposed; } |
dispose()方法是終止消息傳遞,也就付了個disposed常量,而isdisposed()方法就是判斷這個常量而已。這就是整個消息訂閱發送的過程,用的是觀察者模式。
線程切換
在上面模板代碼的基礎上,線程切換只是改變了如下代碼:
1
2
3
|
observable.subscribeon(schedulers.io()) .observeon(androidschedulers.mainthread()) .subscribe(observer); |
下面我們對線程切換的源碼進行一下分析,分為兩部分:subscribeon()和observeon()
subscribeon()
首先是subscribeon()源碼如下:
1
2
3
4
|
public final observable<t> subscribeon(scheduler scheduler) { objecthelper.requirenonnull(scheduler, "scheduler is null" ); return rxjavaplugins.onassembly( new observablesubscribeon<t>( this , scheduler)); } |
我們傳進去了一個scheduler類,scheduler是一個調度類,能夠延時或周期性地去執行一個任務。
scheduler有如下類型:
類型 | 使用方式 | 含義 | 使用場景 |
---|---|---|---|
ioscheduler | schedulers.io() | io操作線程 | 讀寫sd卡文件,查詢數據庫,訪問網絡等io密集型操作 |
newthreadscheduler | schedulers.newthread() | 創建新線程 | 耗時操作等 |
singlescheduler | schedulers.single() | 單例線程 | 只需一個單例線程時 |
computationscheduler | schedulers.computation() | cpu計算操作線程 | 圖片壓縮取樣、xml,json解析等cpu密集型計算 |
trampolinescheduler | schedulers.trampoline() | 當前線程 | 需要在當前線程立即執行任務時 |
handlerscheduler | androidschedulers.mainthread() | android主線程 | 更新ui等 |
接著就沒什么了,只是返回一個observablesubscribeon對象而已。
observeon()
首先看源碼如下:
1
2
3
4
5
6
7
8
9
|
public final observable<t> observeon(scheduler scheduler) { return observeon(scheduler, false , buffersize()); } public final observable<t> observeon(scheduler scheduler, boolean delayerror, int buffersize) { objecthelper.requirenonnull(scheduler, "scheduler is null" ); objecthelper.verifypositive(buffersize, "buffersize" ); return rxjavaplugins.onassembly( new observableobserveon<t>( this , scheduler, delayerror, buffersize)); } |
這里也是沒什么,只是最終返回一個observableobserveon對象而已。
接著還是像原來那樣調用subscribe()方法進行訂閱,看起來好像整體變化不大,就是封裝了一些對象而已,不過著恰恰是rxjava源碼的精華,當他再次調用subscribeactual()方法時,已經不是之前的observablecreate()里subscribeactual方法了,而是最先調用observableobserveon的subscribeactual()方法,對應源碼如下:
1
2
3
4
5
6
7
8
|
protected void subscribeactual(observer<? super t> observer) { if (scheduler instanceof trampolinescheduler) { source.subscribe(observer); } else { scheduler.worker w = scheduler.createworker(); source.subscribe( new observeonobserver<t>(observer, w, delayerror, buffersize)); } } |
在這里有兩點要講,一點是observeonobserver是執行觀察者的線程,后面還會詳解,然后就是source.subscribe,這個source.subscribe調的是observablesubscribeon的subscribe方法,而subscribe方法因為繼承的也是observable,是observable里的方法,所以和上面的observablecreate一樣的方法,所以會調用observablesubscribeon里的subscribeactual()方法,對應的代碼如下:
1
2
3
4
5
|
public void subscribeactual( final observer<? super t> s) { final subscribeonobserver<t> parent = new subscribeonobserver<t>(s); s.onsubscribe(parent); parent.setdisposable(scheduler.scheduledirect( new subscribetask(parent))); } |
上面代碼中,首先把observeonobserver返回給來的用subscribeonobserver“包裝”起來,然后在回調observer的onsubscribe(),就是對應模板代碼的onsubscribe()方法。
接著看subscribetask類的源碼:
1
2
3
4
5
6
7
8
9
10
|
final class subscribetask implements runnable { private final subscribeonobserver<t> parent; subscribetask(subscribeonobserver<t> parent) { this .parent = parent; } @override public void run() { source.subscribe(parent); } } |
其中的source.subscribe(parent),就是我們執行子線程的回調方法,對應我們模板代碼里的被觀察者的subscribe()方法。它放在run()方法里,并且繼承runnable,說明這個類主要是線程運行。接著看scheduler.scheduledirect()方法對應的源碼如下:
1
2
3
4
5
6
7
8
9
10
11
|
public disposable scheduledirect( @nonnull runnable run) { return scheduledirect(run, 0l, timeunit.nanoseconds); } public disposable scheduledirect( @nonnull runnable run, long delay, @nonnull timeunit unit) { final worker w = createworker(); final runnable decoratedrun = rxjavaplugins.onschedule(run); disposetask task = new disposetask(decoratedrun, w); w.schedule(task, delay, unit); return task; } |
在這里,createworker()也是一個抽象方法,調用的是我們的調度類對應的schedulers類里面的方法,這里是ioscheduler類,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
public final class ioscheduler extends scheduler{ final atomicreference<cachedworkerpool> pool; //省略.... public worker createworker() { return new eventloopworker(pool.get()); } static final class eventloopworker extends scheduler.worker { private final compositedisposable tasks; private final cachedworkerpool pool; private final threadworker threadworker; final atomicboolean once = new atomicboolean(); eventloopworker(cachedworkerpool pool) { this .pool = pool; this .tasks = new compositedisposable(); this .threadworker = pool.get(); } //省略.... @nonnull @override public disposable schedule( @nonnull runnable action, long delaytime, @nonnull timeunit unit) { if (tasks.isdisposed()) { // don't schedule, we are unsubscribed return emptydisposable.instance; } return threadworker.scheduleactual(action, delaytime, unit, tasks); } } } static final class cachedworkerpool implements runnable { //省略.... threadworker get() { if (allworkers.isdisposed()) { return shutdown_thread_worker; } while (!expiringworkerqueue.isempty()) { threadworker threadworker = expiringworkerqueue.poll(); if (threadworker != null ) { return threadworker; } } threadworker w = new threadworker(threadfactory); allworkers.add(w); return w; } //省略.... } |
這就是ioscheduler的createworker()的方法,其實最主要的意思就是獲取線程池,以便于生成子線程,讓subscribetask()可以運行。然后直接調用 w.schedule(task, delay, unit)方法讓它在線程池里執行。上面中那threadworker的源碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
static final class threadworker extends newthreadworker { private long expirationtime; threadworker(threadfactory threadfactory) { super (threadfactory); this .expirationtime = 0l; } //省略代碼.... } public class newthreadworker extends scheduler.worker implements disposable { private final scheduledexecutorservice executor; public newthreadworker(threadfactory threadfactory) { executor = schedulerpoolfactory.create(threadfactory); } public scheduledrunnable scheduleactual( final runnable run, long delaytime, @nonnull timeunit unit, @nullable disposablecontainer parent) { runnable decoratedrun = rxjavaplugins.onschedule(run); scheduledrunnable sr = new scheduledrunnable(decoratedrun, parent); if (parent != null ) { if (!parent.add(sr)) { return sr; } } future<?> f; try { if (delaytime <= 0 ) { f = executor.submit((callable<object>)sr); } else { f = executor.schedule((callable<object>)sr, delaytime, unit); } sr.setfuture(f); } catch (rejectedexecutionexception ex) { if (parent != null ) { parent.remove(sr); } rxjavaplugins.onerror(ex); } return sr; } } |
可以看到,這就調了原始的javaapi來進行線程池操作。
然后最后一環在子線程調用source.subscribe(parent)方法,然后回調剛開始創建的observablecreate的subscribeactual(),既:
1
2
3
4
5
6
7
8
9
10
|
protected void subscribeactual(observer<? super t> observer) { createemitter<t> parent = new createemitter<t>(observer); observer.onsubscribe(parent); try { source.subscribe(parent); } catch (throwable ex) { exceptions.throwiffatal(ex); parent.onerror(ex); } } |
進行消息的訂閱綁定。
當我們在調用 emitter.onnext(內容)時,是在io線程里的,那回調的onnext()又是什么時候切換的?那就是前面為了整個流程流暢性沒講的在observeon()里的observeonobserver是執行觀察者的線程的過程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
class observeonobserver<t> extends basicintqueuedisposable<t> implements observer<t>, runnable { //省略代碼.... observeonobserver(observer<? super t> actual, scheduler.worker worker, boolean delayerror, int buffersize) { this .actual = actual; this .worker = worker; this .delayerror = delayerror; this .buffersize = buffersize; } @override public void onsubscribe(disposable s) { if (disposablehelper.validate( this .s, s)) { this .s = s; if (s instanceof queuedisposable) { @suppresswarnings ( "unchecked" ) queuedisposable<t> qd = (queuedisposable<t>) s; int m = qd.requestfusion(queuedisposable.any | queuedisposable.boundary); if (m == queuedisposable.sync) { sourcemode = m; queue = qd; done = true ; actual.onsubscribe( this ); schedule(); return ; } if (m == queuedisposable.async) { sourcemode = m; queue = qd; actual.onsubscribe( this ); return ; } } queue = new spsclinkedarrayqueue<t>(buffersize); actual.onsubscribe( this ); } } @override public void onnext(t t) { if (done) { return ; } if (sourcemode != queuedisposable.async) { queue.offer(t); } schedule(); } void schedule() { if (getandincrement() == 0 ) { worker.schedule( this ); } } //省略代碼.... } |
當調用emitter.onnext(內容)方法,會調用上面的onnext()方法,然后在這個方法里會把數據壓入一個隊列,然后執行worker.schedule(this)方法,work是什么呢,還記得androidschedulers.mainthread()嗎,這個對應這個handlerscheduler這個類,所以createworker()對應著:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
private static final class mainholder { static final scheduler default = new handlerscheduler( new handler(looper.getmainlooper())); } public worker createworker() { return new handlerworker(handler); } private static final class handlerworker extends worker { private final handler handler; private volatile boolean disposed; handlerworker(handler handler) { this .handler = handler; } @override public disposable schedule(runnable run, long delay, timeunit unit) { if (run == null ) throw new nullpointerexception( "run == null" ); if (unit == null ) throw new nullpointerexception( "unit == null" ); if (disposed) { return disposables.disposed(); } run = rxjavaplugins.onschedule(run); scheduledrunnable scheduled = new scheduledrunnable(handler, run); message message = message.obtain(handler, scheduled); message.obj = this ; // used as token for batch disposal of this worker's runnables. handler.sendmessagedelayed(message, unit.tomillis(delay)); if (disposed) { handler.removecallbacks(scheduled); return disposables.disposed(); } return scheduled; } } |
在next()方法里,運用android自帶的handler消息機制,通過把方法包裹在message里,同通過handler.sendmessagedelayed()發送消息,就會在ui線程里回調next()方法,從而實現從子線程切換到android主線程的操作。我們在主線程拿到數據就可以進行各種在主線程的操作了。
總結一下:
observablecreate 一> observablesubscribeon 一> observableobserveon為初始化順序
當調用observable.subscribe(observer)時的執行順序
observableobserveon 一> observablesubscribeon 一> observablecreate
當發送消息的執行順序
observablecreate 一> observablesubscribeon 一> observableobserveon
以上就是消息訂閱和線程切換的源碼的所有講解了。
為了讓你們理解更清楚,我仿照rxjava寫了大概的消息訂閱和線程切換的最基本代碼和基本功能,以幫助你們理解
https://github.com/jack921/rxjava2demo
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.jianshu.com/p/264b68fd96fa