基于RxJava 2.0+版本,對RxJava的訂閱源碼進行簡單分析。
1. 使用實例
我們在使用RxJava2.0時,一般像下面這樣使用。
//1.創建被觀察者
val flowable = Flowable.create(object : FlowableOnSubscribe<String> {
@Throws(Exception::class)
override fun subscribe(e: FlowableEmitter<String>) {
e.onNext("Hello")
e.onNext("World")
e.onNext("!")
//注意在此調用onComplete方法結束事件的處理
e.onComplete()
}
}, BackpressureStrategy.BUFFER)
// 2.創建觀察者
val subscriber = object : Subscriber<String> {
override fun onSubscribe(s: Subscription) {
println("onSubscribe")
// 不調用方法,無法發送流。
s.request(Long.MAX_VALUE)
}
override fun onNext(s: String) {
println(s)
}
override fun onError(t: Throwable) {
t.printStackTrace()
}
override fun onComplete() {
println("onComplete")
}
}
// 3.訂閱
flowable.subscribe(subscriber)
以上代碼基于Kotlin實現,Java實現方式基本類似。
2. 源碼分析
2.1 創建被觀察者
//1.創建被觀察者
val flowable = Flowable.create(object : FlowableOnSubscribe<String> {
// 1. 方法在產生訂閱關系后被調用
@Throws(Exception::class)
override fun subscribe(e: FlowableEmitter<String>) {
// 使用發射器發送事件
e.onNext("Hello")
e.onNext("World")
e.onNext("!")
//注意在此調用onComplete方法結束事件的發送
e.onComplete()
}
}, BackpressureStrategy.BUFFER)
FlowableOnSubscribe
public interface FlowableOnSubscribe<T> {
/**
* Called for each Subscriber that subscribes.
* @param emitter the safe emitter instance, never null
* @throws Exception on error
*/
void subscribe(@NonNull FlowableEmitter<T> emitter) throws Exception;
}
FlowableOnSubscribe接口在發生調閱關系時被調用,用于控制處理、發送事件。
FlowableEmitter
事件發射器,可以調用其接口來發送事件。
public interface FlowableEmitter<T> extends Emitter<T> {
/**
* Sets a Disposable on this emitter; any previous Disposable
* or Cancellation will be disposed/cancelled.
* @param s the disposable, null is allowed
*/
void setDisposable(@Nullable Disposable s);
/**
* Sets a Cancellable on this emitter; any previous Disposable
* or Cancellation will be disposed/cancelled.
* @param c the cancellable resource, null is allowed
*/
void setCancellable(@Nullable Cancellable c);
/**
* The current outstanding request amount.
* <p>This method is thread-safe.
* @return the current outstanding request amount
*/
long requested();
/**
* Returns true if the downstream cancelled the sequence or the
* emitter was terminated via {@link #onError(Throwable)}, {@link #onComplete} or a
* successful {@link #tryOnError(Throwable)}.
* <p>This method is thread-safe.
* @return true if the downstream cancelled the sequence or the emitter was terminated
*/
boolean isCancelled();
/**
* Ensures that calls to onNext, onError and onComplete are properly serialized.
* @return the serialized FlowableEmitter
*/
@NonNull
FlowableEmitter<T> serialize();
/**
* Attempts to emit the specified {@code Throwable} error if the downstream
* hasn't cancelled the sequence or is otherwise terminated, returning false
* if the emission is not allowed to happen due to lifecycle restrictions.
* <p>
* Unlike {@link #onError(Throwable)}, the {@code RxJavaPlugins.onError} is not called
* if the error could not be delivered.
* @param t the throwable error to signal if possible
* @return true if successful, false if the downstream is not able to accept further
* events
* @since 2.1.1 - experimental
*/
@Experimental
boolean tryOnError(@NonNull Throwable t);
}
Emitter
public interface Emitter<T> {
/**
* Signal a normal value.
* @param value the value to signal, not null
*/
void onNext(@NonNull T value);
/**
* Signal a Throwable exception.
* @param error the Throwable to signal, not null
*/
void onError(@NonNull Throwable error);
/**
* Signal a completion.
*/
void onComplete();
}
這個才是真正發送數據的接口定義。
Flowable.Create
public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
ObjectHelper.requireNonNull(source, "source is null");
ObjectHelper.requireNonNull(mode, "mode is null");
return RxJavaPlugins.onAssembly(new FlowableCreate<T>(source, mode));
}
根據FlowableOnSubscribe、背壓策略構造并返回FlowableCreate實例。
RxJavaPlugins.onAssembly
public static <T> Flowable<T> onAssembly(@NonNull Flowable<T> source) {
Function<? super Flowable, ? extends Flowable> f = onFlowableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
如果設置了相關的轉換方法,則調用,否則返回傳入的Flowable。
FlowableCreate-實際創建的對象
- FlowableCreate繼承于Flowable。
- 會根據背壓模式創建不同的發射器,用于訂閱時的回調。
public final class FlowableCreate<T> extends Flowable<T> {
final FlowableOnSubscribe<T> source;
final BackpressureStrategy backpressure;
public FlowableCreate(FlowableOnSubscribe<T> source, BackpressureStrategy backpressure) {
this.source = source;
this.backpressure = backpressure;
}
@Override
public void subscribeActual(Subscriber<? super T> t) {
BaseEmitter<T> emitter;
switch (backpressure) {
case MISSING: {
emitter = new MissingEmitter<T>(t);
break;
}
case ERROR: {
emitter = new ErrorAsyncEmitter<T>(t);
break;
}
case DROP: {
emitter = new DropAsyncEmitter<T>(t);
break;
}
case LATEST: {
emitter = new LatestAsyncEmitter<T>(t);
break;
}
default: {
emitter = new BufferAsyncEmitter<T>(t, bufferSize());
break;
}
}
// 調用Subscriber的onSubscribe方法[onSubscribe(s: Subscription)]
// emitter實際上繼承了Subscription
t.onSubscribe(emitter);
try {
// 調用FlowableOnSubscribe的subscribe方法[subscribe(e: FlowableEmitter<String>)]
// emitter實際上繼承了FlowableEmitter
source.subscribe(emitter);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
emitter.onError(ex);
}
}
}
2.2 創建觀察者
// 定義觀察者
val subscriber = object : Subscriber<String> {
override fun onSubscribe(s: Subscription) {
println("onSubscribe")
// 不調用方法,無法發送流。
s.request(Long.MAX_VALUE)
}
override fun onNext(s: String) {
println(s)
}
override fun onError(t: Throwable) {
t.printStackTrace()
}
override fun onComplete() {
println("onComplete")
}
}
Subscriber
public interface Subscriber<T> {
/**
* Invoked after calling {@link Publisher#subscribe(Subscriber)}.
* <p>
* No data will start flowing until {@link Subscription#request(long)} is invoked.
* <p>
* It is the responsibility of this {@link Subscriber} instance to call {@link Subscription#request(long)} whenever more data is wanted.
* <p>
* The {@link Publisher} will send notifications only in response to {@link Subscription#request(long)}.
*
* @param s
* {@link Subscription} that allows requesting data via {@link Subscription#request(long)}
*/
public void onSubscribe(Subscription s);
/**
* Data notification sent by the {@link Publisher} in response to requests to {@link Subscription#request(long)}.
*
* @param t the element signaled
*/
public void onNext(T t);
/**
* Failed terminal state.
* <p>
* No further events will be sent even if {@link Subscription#request(long)} is invoked again.
*
* @param t the throwable signaled
*/
public void onError(Throwable t);
/**
* Successful terminal state.
* <p>
* No further events will be sent even if {@link Subscription#request(long)} is invoked again.
*/
public void onComplete();
}
該接口主要是定義了事件處理方法,特別需要注意的幾點:
onSubscribe在發生訂閱關系時首先被調用;
除非在該方法中調用了Subscription.request方法,否則數據流不會發送;也可以在該方法中調用Subscription.cancel取消數據流的發送。onError與onComplete方法互斥。
onNext接收事件并處理。
2.3 訂閱
// 3.訂閱
flowable.subscribe(subscriber)
Flowable.subscribe(Subscriber<? super T> s)
public final void subscribe(Subscriber<? super T> s) {
// 我們只實現了Subscriber接口,s為FlowableSubscriber實例
if (s instanceof FlowableSubscriber) {
// 實際調用的是subscribe(FlowableSubscriber<? super T> s)
subscribe((FlowableSubscriber<? super T>)s);
} else {
ObjectHelper.requireNonNull(s, "s is null");
subscribe(new StrictSubscriber<T>(s));
}
}
FlowableSubscriber
public interface FlowableSubscriber<T> extends Subscriber<T> {
/**
* Implementors of this method should make sure everything that needs
* to be visible in {@link #onNext(Object)} is established before
* calling {@link Subscription#request(long)}. In practice this means
* no initialization should happen after the {@code request()} call and
* additional behavior is thread safe in respect to {@code onNext}.
*
* {@inheritDoc}
*/
@Override
void onSubscribe(@NonNull Subscription s);
}
其實FlowableSubscriber與Subscriber的定義相同。
Flowable.subscribe(FlowableSubscriber<? super T> s)
public final void subscribe(FlowableSubscriber<? super T> s) {
ObjectHelper.requireNonNull(s, "s is null");
try {
// 附加操作
Subscriber<? super T> z = RxJavaPlugins.onSubscribe(this, s);
ObjectHelper.requireNonNull(z, "Plugin returned null Subscriber");
// 實際的實現在這里
subscribeActual(z);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Subscription has been set or not
// can't call onSubscribe because the call might have set a Subscription already
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
Flowable.subscribeActual
protected abstract void subscribeActual(Subscriber<? super T> s)
這個方法為抽象方法,那么它的實際實現在哪里呢?答案就是我們在創建Flowable時分析的FlowableCreate。
FlowableCreate.subscribeActual
public final class FlowableCreate<T> extends Flowable<T> {
// 1. 創建Flowable對象時傳入的FlowableOnSubscribe實例
final FlowableOnSubscribe<T> source;
// 1. 創建Flowable對象時傳入的背壓策略
final BackpressureStrategy backpressure;
public FlowableCreate(FlowableOnSubscribe<T> source, BackpressureStrategy backpressure) {
this.source = source;
this.backpressure = backpressure;
}
@Override
public void subscribeActual(Subscriber<? super T> t) {
BaseEmitter<T> emitter;
// 根據不同的背壓策略,創建不同的發射器
switch (backpressure) {
case MISSING: {
emitter = new MissingEmitter<T>(t);
break;
}
case ERROR: {
emitter = new ErrorAsyncEmitter<T>(t);
break;
}
case DROP: {
emitter = new DropAsyncEmitter<T>(t);
break;
}
case LATEST: {
emitter = new LatestAsyncEmitter<T>(t);
break;
}
default: {
// 我們創建的是這個
emitter = new BufferAsyncEmitter<T>(t, bufferSize());
break;
}
}
// 1. 首先回調Subscriber的onSubscribe方法
t.onSubscribe(emitter);
try {
// 2.回調FlowableOnSubscribe的subscribe方法
// 我們一般在subscribe方法中發送數據
source.subscribe(emitter);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
// 發生異常,則直接回調onError接口
emitter.onError(ex);
}
}
}
BufferAsyncEmitter
BufferAsyncEmitter系FlowableCreate的靜態內部類,Emitter設計為對外透明,用戶只需設置背壓策略即可。
static final class BufferAsyncEmitter<T> extends BaseEmitter<T> {
private static final long serialVersionUID = 2427151001689639875L;
final SpscLinkedArrayQueue<T> queue;
Throwable error;
volatile boolean done;
final AtomicInteger wip;
// 1. actual實際的訂閱者。
// 2. capacityHint默認值為128。
BufferAsyncEmitter(Subscriber<? super T> actual, int capacityHint) {
super(actual);
this.queue = new SpscLinkedArrayQueue<T>(capacityHint);
this.wip = new AtomicInteger();
}
// 我們在Flowable的subscribe方法,調用此接口來發送事件。
@Override
public void onNext(T t) {
// 1. 當我們在Flowable.subscribe中調用onComplete方法后,done為true,事件不再發送
// 2. 當我們在Flowable.subscribe調用cancel方法后,isCancelled返回true
// 3. 當我們在Subscriber的onSubscribe方法調用Subsription.cancel方法后,isCancelled返回true
if (done || isCancelled()) {
return;
}
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
// 將事件加入隊列
queue.offer(t);
drain();
}
@Override
public boolean tryOnError(Throwable e) {
if (done || isCancelled()) {
return false;
}
if (e == null) {
e = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
}
error = e;
done = true;
drain();
return true;
}
// 我們在Flowable的subscribe方法調用該方法來結束事件發送
@Override
public void onComplete() {
done = true;
drain();
}
// 調用request方法后,該方法會被調用
@Override
void onRequested() {
drain();
}
@Override
void onUnsubscribed() {
if (wip.getAndIncrement() == 0) {
queue.clear();
}
}
void drain() {
// 當前正在進行事件分發,因為在onNext中已經將事件加入隊列,直接返回
if (wip.getAndIncrement() != 0) {
return;
}
int missed = 1;
final Subscriber<? super T> a = actual;
final SpscLinkedArrayQueue<T> q = queue;
// 進入循環進行事件分發
for (;;) {
// 1. 未調用request方法,r==0
// 2. request方法,r==n
long r = get();
long e = 0L;
// 只有調用了request方法,e!=r
while (e != r) {
// 如果已經被取消,清空隊列,直接返回
if (isCancelled()) {
q.clear();
return;
}
boolean d = done;
T o = q.poll();
boolean empty = o == null;
// 判斷事件正常結束or異常
if (d && empty) {
Throwable ex = error;
if (ex != null) {
error(ex);
} else {
complete();
}
return;
}
if (empty) {
break;
}
// 事件不為空,分發事件
a.onNext(o);
e++;
}
// 1.如果未調用request方法,e==r==0
// 2. 調用了request方法,則執行上面的分發代碼,直到e==r
if (e == r) {
if (isCancelled()) {
q.clear();
return;
}
boolean d = done;
boolean empty = q.isEmpty();
if (d && empty) {
Throwable ex = error;
if (ex != null) {
error(ex);
} else {
complete();
}
return;
}
}
if (e != 0) {
BackpressureHelper.produced(this, e);
}
// 未調用request方法,missed==0
missed = wip.addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
}
BaseEmitter
由上面的分析,我們知道BufferAsyncEmitter繼承BufferAsyncEmitter。
在示例中,我們說明了只有在Subscriber.onSubscribe方法中調用Subscription的request方法,事件才能發送。
示例代碼:
val subsrciber = object : Subscriber<String> {
//由訂閱時的代碼分析可知, s此時實際上為BufferAsyncEmitter示例
override fun onSubscribe(s: Subscription) {
println("onSubscribe")
// 不調用方法,無法發送流。
s.request(Long.MAX_VALUE)
}
}
BaseEmitter
abstract static class BaseEmitter<T>
extends AtomicLong
implements FlowableEmitter<T>, Subscription {
BaseEmitter(Subscriber<? super T> actual) {
this.actual = actual;
this.serial = new SequentialDisposable();
}
@Override
public void onComplete() {
complete();
}
protected void complete() {
if (isCancelled()) {
return;
}
try {
actual.onComplete();
} finally {
serial.dispose();
}
}
@Override
public final void request(long n) {
if (SubscriptionHelper.validate(n)) {
// 此處設置了AtomicLong為n
BackpressureHelper.add(this, n);
onRequested();
}
}
// 省略......
}
訂閱的核心是FlowableCreate和BaseEmitter這兩個類,實現上還是比較清晰明了的。
3. 總結
本章只是簡單的分析了RxJava2.0的訂閱源碼,RxJava的使用和實現遠比此復雜,在此拋磚引玉,希望大家能活用、善用RxJava來提高工作效率,早日解放自己。