RxJava2 Subject源码浅析

714 阅读7分钟

关于Observable的源码解析可以看Rxjava2 Observable源码浅析

关于Flowable的源码解析可以看RxJava2 Flowable源码浅析

前言

关于suject可能在Android用的不多,一般来说subject都是用于跨组件的通信工具,可选库可以选RxBusEventBus。 官方的解释,Subject在同一时间内,既可以作为Observable,也可以作为Observer,在继承实现的关系上也是可以看出的。

//既是数据源,也是数据订阅者
public abstract class Subject<T> extends Observable<T> implements Observer<T>

在RxJava2.x中,官方一共为我们提供了以下几种Subject:

  • ReplaySubject (释放接收到的所有数据)
  • BehaviorSubject (释放订阅前最后一个数据和订阅后接收到的所有数据)
  • PublishSubject (释放订阅后接收到的数据)
  • AsyncSubject (仅释放接收到的最后一个数据)
  • SerializedSubject(串行Subject)
  • UnicastSubject (仅支持订阅一次的Subject)

ReplaySubject

public final class ReplaySubject<T> extends Subject<T> {
    //数据缓存区
    final ReplayBuffer<T> buffer;
    //订阅者列表
    final AtomicReference<ReplayDisposable<T>[]> observers;
    
    @SuppressWarnings("rawtypes")
    static final ReplayDisposable[] EMPTY = new ReplayDisposable[0];//用于表示无订阅者
    
    @SuppressWarnings("rawtypes")
    static final ReplayDisposable[] TERMINATED = new ReplayDisposable[0];//用于表示结束
    
    //标记是否已经完成(调用过onComplete/onError)
    boolean done;
    
    public static <T> ReplaySubject<T> create() {
        //buffer为UnboundedReplayBuffer
        return new ReplaySubject<T>(new UnboundedReplayBuffer<T>(16));
    }
    
    //继承于Observable,subscribe最终调用到该方法重新下发数据
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        ReplayDisposable<T> rs = new ReplayDisposable<T>(observer, this);
        observer.onSubscribe(rs);

        if (!rs.cancelled) {
            if (add(rs)) {
                if (rs.cancelled) {
                    remove(rs);
                    return;
                }
            }
            //通过buffer重发数据
            buffer.replay(rs);
        }
    }
    
    @Override
    public void onNext(T t) {
        ObjectHelper.requireNonNull(t, "onNext called with null. Null values are generally not allowed in 2.x operators and sources.");
        if (done) {
            return;
        }

        ReplayBuffer<T> b = buffer;
        b.add(t);//将数据插入buffer

        for (ReplayDisposable<T> rs : observers.get()) {
            b.replay(rs);//调用replay
        }
    }
    
    //ReplayDisposable继承于AtomicInteger,用于标识onNext下发(buffer#replay)过几次
    static final class ReplayDisposable<T> extends AtomicInteger implements Disposable {

        private static final long serialVersionUID = 466549804534799122L;
        final Observer<? super T> downstream;
        final ReplaySubject<T> state;

        Object index;//用于记录对应已经下发过buff数据的最后index,避免数据重复下发

        volatile boolean cancelled;

        ReplayDisposable(Observer<? super T> actual, ReplaySubject<T> state) {
            this.downstream = actual;
            this.state = state;
        }

        @Override
        public void dispose() {
            if (!cancelled) {
                cancelled = true;
                state.remove(this);
            }
        }

        @Override
        public boolean isDisposed() {
            return cancelled;
        }
    }
    
    static final class UnboundedReplayBuffer<T>
    extends AtomicReference<Object>
    implements ReplayBuffer<T> {
        private static final long serialVersionUID = -733876083048047795L;

        final List<Object> buffer;

        volatile boolean done;

        volatile int size;

        .....
        
        @Override
        @SuppressWarnings("unchecked")
        public void replay(ReplayDisposable<T> rs) {
            if (rs.getAndIncrement() != 0) {//已经被replay了
                return;
            }

            int missed = 1;
            final List<Object> b = buffer;
            final Observer<? super T> a = rs.downstream;
            //获取已下发数据在缓存中的index
            Integer indexObject = (Integer)rs.index;
            int index;
            if (indexObject != null) {
                index = indexObject;
            } else {
                index = 0;
                rs.index = 0;
            }

            for (;;) {

                if (rs.cancelled) {
                    rs.index = null;
                    return;
                }

                int s = size;

                while (s != index) {

                    if (rs.cancelled) {
                        rs.index = null;
                        return;
                    }
                    //获取index对应数据
                    Object o = b.get(index);

                    if (done) {//已调用onComplete/onError
                        if (index + 1 == s) {
                            s = size;
                            if (index + 1 == s) {
                                if (NotificationLite.isComplete(o)) {
                                    a.onComplete();
                                } else {
                                    a.onError(NotificationLite.getError(o));
                                }
                                rs.index = null;
                                rs.cancelled = true;
                                return;
                            }
                        }
                    }
        
                    a.onNext((T)o);//下发
                    index++;//index自增
                }

                if (index != size) {
                    continue;
                }
                //更新index
                rs.index = index;
                //参考Flowable/Observable,主要用于处理多次调用onNext
                missed = rs.addAndGet(-missed);
                if (missed == 0) {
                    break;
                }
            }
        }
        ...
    }
}

ReplaySubject看着代码很长,但逻辑很简单,主要就是通过buffer(ArrayList)缓存数据,在订阅时重新下发。重要代码已经加上注释。

PublishSubject

public final class PublishSubject<T> extends Subject<T> {
    static final PublishDisposable[] TERMINATED = new PublishDisposable[0];
    static final PublishDisposable[] EMPTY = new PublishDisposable[0];
    final AtomicReference<PublishDisposable<T>[]> subscribers;
    Throwable error;

    @CheckReturnValue
    @NonNull
    public static <T> PublishSubject<T> create() {
        return new PublishSubject<T>();
    }

    @SuppressWarnings("unchecked")
    PublishSubject() {
        subscribers = new AtomicReference<PublishDisposable<T>[]>(EMPTY);
    }

    @Override
    protected void subscribeActual(Observer<? super T> t) {
        PublishDisposable<T> ps = new PublishDisposable<T>(t, this);
        t.onSubscribe(ps);
        if (add(ps)) {
            // if cancellation happened while a successful add, the remove() didn't work
            // so we need to do it again
            if (ps.isDisposed()) {
                remove(ps);
            }
        } else {
            Throwable ex = error;
            if (ex != null) {
                t.onError(ex);
            } else {
                t.onComplete();
            }
        }
    }

    @Override
    public void onNext(T t) {
        ObjectHelper.requireNonNull(t, "onNext called with null. Null values are generally not allowed in 2.x operators and sources.");
        for (PublishDisposable<T> pd : subscribers.get()) {
            pd.onNext(t);
        }
    }

    static final class PublishDisposable<T> extends AtomicBoolean implements Disposable {
    
        PublishDisposable(Observer<? super T> actual, PublishSubject<T> parent) {
            this.downstream = actual;
            this.parent = parent;
        }

        public void onNext(T t) {
            if (!get()) {//dispose()会将自身设为true
                downstream.onNext(t);
            }
        }
    }
}

emmm...PublishSubject是最简单de,因为没有缓存机制,只要直接将onNext的数据下发到PublishDisposable即可。

BehaviorSubject

public final class BehaviorSubject<T> extends Subject<T> {

    private static final Object[] EMPTY_ARRAY = new Object[0];

    final AtomicReference<Object> value;

    final AtomicReference<BehaviorDisposable<T>[]> subscribers;

    static final BehaviorDisposable[] EMPTY = new BehaviorDisposable[0];

    static final BehaviorDisposable[] TERMINATED = new BehaviorDisposable[0];
    final ReadWriteLock lock;
    //读写锁,数据源和下发数据到订阅者明显是生产者-消费者模式
    final Lock readLock;
    final Lock writeLock;

    final AtomicReference<Throwable> terminalEvent;

    long index;//用于记录当前下发的次数

    public static <T> BehaviorSubject<T> create() {
        return new BehaviorSubject<T>();
    }

    BehaviorSubject() {
        this.lock = new ReentrantReadWriteLock();
        this.readLock = lock.readLock();
        this.writeLock = lock.writeLock();
        this.subscribers = new AtomicReference<BehaviorDisposable<T>[]>(EMPTY);
        this.value = new AtomicReference<Object>();
        this.terminalEvent = new AtomicReference<Throwable>();
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        BehaviorDisposable<T> bs = new BehaviorDisposable<T>(observer, this);
        observer.onSubscribe(bs);//开始订阅
        if (add(bs)) {//加入订阅队列
            if (bs.cancelled) {
                remove(bs);
            } else {
                bs.emitFirst();//下发最近的一次数据
            }
        } else {
            Throwable ex = terminalEvent.get();
            if (ex == ExceptionHelper.TERMINATED) {
                observer.onComplete();
            } else {
                observer.onError(ex);
            }
        }
    }

    @Override
    public void onNext(T t) {
        ObjectHelper.requireNonNull(t, "onNext called with null. Null values are generally not allowed in 2.x operators and sources.");

        if (terminalEvent.get() != null) {
            return;
        }
        Object o = NotificationLite.next(t);
        setCurrent(o);
        for (BehaviorDisposable<T> bs : subscribers.get()) {
            bs.emitNext(o, index);//最终通过test方法下发
        }
    }
    
    @Override
    public void onError(Throwable t) {
        ObjectHelper.requireNonNull(t, "onError called with null. Null values are generally not allowed in 2.x operators and sources.");
        if (!terminalEvent.compareAndSet(null, t)) {
            RxJavaPlugins.onError(t);
            return;
        }
        Object o = NotificationLite.error(t);
        for (BehaviorDisposable<T> bs : terminate(o)) {
            bs.emitNext(o, index);//最终通过test方法下发
        }
    }

    @Override
    public void onComplete() {
        if (!terminalEvent.compareAndSet(null, ExceptionHelper.TERMINATED)) {
            return;
        }
        Object o = NotificationLite.complete();
        for (BehaviorDisposable<T> bs : terminate(o)) {
            bs.emitNext(o, index);  // relaxed read okay since this is the only mutator thread
        }
    }

    void setCurrent(Object o) {//多线程OnNext,写锁写入数据
        writeLock.lock();
        index++;
        value.lazySet(o);
        writeLock.unlock();
    }

    static final class BehaviorDisposable<T> implements Disposable, NonThrowingPredicate<Object> {

        final Observer<? super T> downstream;
        final BehaviorSubject<T> state;

        boolean next;
        boolean emitting;//用于标识是否在检测缓存数据数据等待发送
        AppendOnlyLinkedArrayList<Object> queue;

        boolean fastPath;

        volatile boolean cancelled;

        long index;//用于记录当前下发的次数

        BehaviorDisposable(Observer<? super T> actual, BehaviorSubject<T> state) {
            this.downstream = actual;
            this.state = state;
        }

        @Override
        public void dispose() {
            if (!cancelled) {
                cancelled = true;

                state.remove(this);
            }
        }

        @Override
        public boolean isDisposed() {
            return cancelled;
        }

        void emitFirst() {
            if (cancelled) {
                return;
            }
            Object o;
            synchronized (this) {
                if (cancelled) {
                    return;
                }
                if (next) {
                    return;
                }

                BehaviorSubject<T> s = state;
                Lock lock = s.readLock;

                lock.lock();
                index = s.index;//第一次下发,同步subject的index
                o = s.value.get();
                lock.unlock();

                emitting = o != null;//标记已经在等待下发第一条数据
                next = true;
            }

            if (o != null) {
                if (test(o)) {//complete/error事件才返回true
                    return;
                }
                //循环尝试下发缓存区中的数据
                emitLoop();
            }
        }
        //stateIndex为subject中当次onNext下发的次数
        void emitNext(Object value, long stateIndex) {
            if (cancelled) {
                return;
            }
            if (!fastPath) {//因为可能第一条数据未下发成功
                synchronized (this) {//加锁保证,缓存区检测临界区安全
                    if (cancelled) {
                        return;
                    }
                    
                    //是当前订阅者的第一条数据的index,即应该emitFirst处理,这里不处理
                    if (index == stateIndex) {
                        return;
                    }
                    //在检测缓存区数据则将数据加入缓存区
                    if (emitting) {
                        AppendOnlyLinkedArrayList<Object> q = queue;
                        if (q == null) {
                            q = new AppendOnlyLinkedArrayList<Object>(4);
                            queue = q;
                        }
                        q.add(value);
                        return;
                    }
                    next = true;
                }
                fastPath = true;
            }

            test(value);//下发数据
        }

        @Override
        public boolean test(Object o) {//下发数据,#accept仅complete/error事件才返回true
            return cancelled || NotificationLite.accept(o, downstream);
        }

        void emitLoop() {//循环尝试获取缓存区数据下发
            for (;;) {
                if (cancelled) {
                    return;
                }
                AppendOnlyLinkedArrayList<Object> q;
                synchronized (this) {//加锁保证,缓存区检测临界区安全
                    q = queue;
                    if (q == null) {//无缓存区,标记退出缓存区检测
                        emitting = false;
                        return;
                    }
                    queue = null;
                }

                q.forEachWhile(this);//循环尝试调用test方法下发
            }
        }
    }
}

BehaviorSubject是只缓存最近一条数据,当新的订阅者订阅时,将上次最新的数据下发。最近的数据通过AtomicReference<Object> value保存。

  • 当第一次订阅时,会调用BehaviorDisposable#emitFirst下发第一条数据并读取缓存区数据下发
  • onNext就要考虑如果emitFirst可能在去读缓存区数据则将数据添加如缓存区,否则直接下发

AsyncSubject

AsyncSubject只释放最后一个数据的处理就比较简单,源码里面其实就是在onNext时将数据缓存,在onComplete时先下发再调用下游onComplete,onError则直接下发onError数据不会下发。这里就不贴代码分析了。

SerializedSubject

SerializedSubject其实就是Subject的装饰增强类,通过传入Subject对所有的下发指令(onSubscribeonNextonErroronComplete)在下发之前通过synchronized关键字进行状态判断再下发,从而达到线程安全的效果。

内部实现也是类似于BehaviorSubject将所有事件抽象,然后通过读取缓存区进行下发。

UnicastSubject

UnicastSubject仅支持订阅一次。如果多个订阅者试图订阅,若UnicastSubjectterminate,将会收到IllegalStateException ,若已经terminate,那么只会执行onError或者onComplete方法。