RxJava3 Disposable状态值管理接口笔记:

985 阅读3分钟

Observable发布数据并由Observer消费。消费者应该有一个可以放弃操作资源的能力,Disposable的设计在于解耦,而状态管理是针对Observer端的,所以在实现Observer时顺带实现Disposable接口,这样消费端便具备了状态管理的能力。单单具备这个能力还不够,还需要Observable的配合。

@CheckReturnValue
@SchedulerSupport("none")
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {
    ObjectHelper.requireNonNull(onNext, "onNext is null");
    ObjectHelper.requireNonNull(onError, "onError is null");
    ObjectHelper.requireNonNull(onComplete, "onComplete is null");
    LambdaObserver<T> ls = new LambdaObserver(onNext, onError, onComplete, Functions.emptyConsumer());
    this.subscribe((Observer)ls);
    return ls;
}

关注Observable核心方法,可以看到,方法返回一个Disposable,Observer会作为Disposable的角色返回,并被我们程序得到,进而我们能够对Observer的状态进行控制。

//状态管理接口,非函数式接口,无法通过函数式的方式来快速使用该接口。
public interface Disposable {
    void dispose();

    boolean isDisposed();
}

接下来看ObservableCache#subscribeActual(Observer<? super T> t)的实现:

protected void subscribeActual(Observer<? super T> t) {
    ObservableCache.CacheDisposable<T> consumer = new ObservableCache.CacheDisposable(t, this);
    t.onSubscribe(consumer);
    this.add(consumer);
    //首次订阅,这个方法将订阅者和ObservableCache建立联系,实际调用的就是ObservableCache,于是可以将Observer和ObservableCache分开控制状态。
    if (!this.once.get() && this.once.compareAndSet(false, true)) {
        this.source.subscribe(this);
    } else {
        this.replay(consumer);
    }
}
可以看到,在真正产生订阅的subscribeActual()方法中,首先包装了CacheDisposable:

static final class CacheDisposable<T> extends AtomicInteger implements Disposable {
    private static final long serialVersionUID = 6770240836423125754L;
    final Observer<? super T> downstream;
    final ObservableCache<T> parent;
    ObservableCache.Node<T> node;
    int offset;
    long index;
    volatile boolean disposed;

    CacheDisposable(Observer<? super T> downstream, ObservableCache<T> parent) {
        this.downstream = downstream;
        this.parent = parent;
        this.node = parent.head;
    }

    
    public void dispose() {
        if (!this.disposed) {
            this.disposed = true;
            this.parent.remove(this);
        }

    }

    public boolean isDisposed() {
        return this.disposed;
    }
}

再来看看remove方法:

//如果Observable是一个无限流,哪怕订阅者自行结束,保留的EMPTY也会引导Observable无限执行下去。
void remove(CacheDisposable<T> consumer) {
    for (;;) {
        CacheDisposable<T>[] current = observers.get();
        int n = current.length;
        if (n == 0) {
            return;
        }

        int j = -1;
        for (int i = 0; i < n; i++) {
            if (current[i] == consumer) {
                j = i;
                break;
            }
        }

        if (j < 0) {
            return;
        }
        CacheDisposable<T>[] next;

        //最后总是保留一个EMPTY
        if (n == 1) {
            next = EMPTY;
        } else {
            next = new CacheDisposable[n - 1];
            System.arraycopy(current, 0, next, 0, j);
            System.arraycopy(current, j + 1, next, j, n - j - 1);
        }

        if (observers.compareAndSet(current, next)) {
            return;
        }
    }
}

从上篇解读的ObservableSource<T>.subscribe(this)可以知道,内部调用了Observer的onNext()、onError()或者onComplete()方法。对Observer来说,要想主动结束订阅,就在ObservableSource<T>.subscribe(this)处。来看下ObservableCache的下发元素方法:

@Override
public void onNext(T t) {
    int tailOffset = this.tailOffset;
    // if the current tail node is full, create a fresh node
    if (tailOffset == capacityHint) {
        Node<T> n = new Node<T>(tailOffset);
        n.values[0] = t;
        this.tailOffset = 1;
        tail.next = n;
        tail = n;
    } else {
        tail.values[tailOffset] = t;
        this.tailOffset = tailOffset + 1;
    }
    size++;
    for (CacheDisposable<T> consumer : observers.get()) {
        replay(consumer);
    }
}

//下面的onError()、onComplete()结束的时候,执行observers.getAndSet(TERMINATED),设置订阅者数组为空,并返回之前数组中的订阅者,通过遍历让订阅者分别结束自己的消费处理流程。
@SuppressWarnings("unchecked")
@Override
public void onError(Throwable t) {
    error = t;
    done = true;
    for (CacheDisposable<T> consumer : observers.getAndSet(TERMINATED)) {
        replay(consumer);
    }
}

@SuppressWarnings("unchecked")
@Override
public void onComplete() {
    done = true;
    for (CacheDisposable<T> consumer : observers.getAndSet(TERMINATED)) {
        replay(consumer);
    }
}

再来看replay(consumer):
if (consumer.disposed) {
            consumer.node = null;
            return;
        }


因为ObservableCache实现了Observer,这里的Observer就是ObservableCache。

不管是Observable还是Observer都应该有能力结束订阅,但Observer解除订阅和Observable解除订阅不应该混为一谈。所以订阅时,使用装饰者设计模式对Observer做了第一次包装为CacheDisposable,这样订阅者便拥有了解除订阅的能力。对于发布订阅的过程,Observable应该主导onNext()、onComplete()、onError(),也就是ObservableCache,并将CacheDisposable纳入其中管理,最后通source.subscribe(this)将两者联系起来,从而做到功能上的解耦。