RxJava中的Subscriber

要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展

    implementation 'io.reactivex:rxandroid:1.2.1'
    implementation 'io.reactivex:rxjava:1.2.0'

Subscriber翻译成中文为订阅者,这里要和Subscribe区分开,虽然只有最后差一个字母,但是Subscribe是动词订阅的意思,在RXjava中是observable的一个方法,也可以称作函数

observable.subscribe(subscriber);`

observable就是我们的被观察者,也就是事件发生源。

由于Subscriber源代码不多,就直接贴源码啦

/**
 * Provides a mechanism for receiving push-based notifications from Observables, and permits manual
 * unsubscribing from these Observables.
 * <p>
 * After a Subscriber calls an {@link Observable}'s {@link Observable#subscribe subscribe} method, the
 * {@link Observable} calls the Subscriber's {@link #onNext} method to emit items. A well-behaved
 * {@link Observable} will call a Subscriber's {@link #onCompleted} method exactly once or the Subscriber's
 * {@link #onError} method exactly once.
 *
 * @see <a href="http://reactivex.io/documentation/observable.html">ReactiveX documentation: Observable</a>
 * @param <T>
 *          the type of items the Subscriber expects to observe
 */
public abstract class Subscriber<T> implements Observer<T>, Subscription {

    // represents requested not set yet
    private static final long NOT_SET = Long.MIN_VALUE;

    private final SubscriptionList subscriptions;
    private final Subscriber<?> subscriber;
    /* protected by `this` */
    private Producer producer;
    /* protected by `this` */
    private long requested = NOT_SET; // default to not set

    protected Subscriber() {
        this(null, false);
    }

    /**
     * Construct a Subscriber by using another Subscriber for backpressure and
     * for holding the subscription list (when <code>this.add(sub)</code> is
     * called this will in fact call <code>subscriber.add(sub)</code>).
     *
     * @param subscriber
     *            the other Subscriber
     */
    protected Subscriber(Subscriber<?> subscriber) {
        this(subscriber, true);
    }

    /**
     * Construct a Subscriber by using another Subscriber for backpressure and
     * optionally for holding the subscription list (if
     * <code>shareSubscriptions</code> is <code>true</code> then when
     * <code>this.add(sub)</code> is called this will in fact call
     * <code>subscriber.add(sub)</code>).
     * <p>
     * To retain the chaining of subscribers when setting
     * <code>shareSubscriptions</code> to <code>false</code>, add the created
     * instance to {@code subscriber} via {@link #add}.
     *
     * @param subscriber
     *            the other Subscriber
     * @param shareSubscriptions
     *            {@code true} to share the subscription list in {@code subscriber} with
     *            this instance
     * @since 1.0.6
     */
    protected Subscriber(Subscriber<?> subscriber, boolean shareSubscriptions) {
        this.subscriber = subscriber;
        this.subscriptions = shareSubscriptions && subscriber != null ? subscriber.subscriptions : new SubscriptionList();
    }

    /**
     * Adds a {@link Subscription} to this Subscriber's list of subscriptions if this list is not marked as
     * unsubscribed. If the list <em>is</em> marked as unsubscribed, {@code add} will indicate this by
     * explicitly unsubscribing the new {@code Subscription} as well.
     *
     * @param s
     *            the {@code Subscription} to add
     */
    public final void add(Subscription s) {
        subscriptions.add(s);
    }

    @Override
    public final void unsubscribe() {
        subscriptions.unsubscribe();
    }

    /**
     * Indicates whether this Subscriber has unsubscribed from its list of subscriptions.
     *
     * @return {@code true} if this Subscriber has unsubscribed from its subscriptions, {@code false} otherwise
     */
    @Override
    public final boolean isUnsubscribed() {
        return subscriptions.isUnsubscribed();
    }

    /**
     * This method is invoked when the Subscriber and Observable have been connected but the Observable has
     * not yet begun to emit items or send notifications to the Subscriber. Override this method to add any
     * useful initialization to your subscription, for instance to initiate backpressure.
     */
    public void onStart() {
        // do nothing by default
    }

    /**
     * Request a certain maximum number of emitted items from the Observable this Subscriber is subscribed to.
     * This is a way of requesting backpressure. To disable backpressure, pass {@code Long.MAX_VALUE} to this
     * method.
     * <p>
     * Requests are additive but if a sequence of requests totals more than {@code Long.MAX_VALUE} then
     * {@code Long.MAX_VALUE} requests will be actioned and the extras <i>may</i> be ignored. Arriving at
     * {@code Long.MAX_VALUE} by addition of requests cannot be assumed to disable backpressure. For example,
     * the code below may result in {@code Long.MAX_VALUE} requests being actioned only.
     *
     * <pre>
     * request(100);
     * request(Long.MAX_VALUE-1);
     * </pre>
     *
     * @param n the maximum number of items you want the Observable to emit to the Subscriber at this time, or
     *           {@code Long.MAX_VALUE} if you want the Observable to emit items at its own pace
     * @throws IllegalArgumentException
     *             if {@code n} is negative
     */
    protected final void request(long n) {
        if (n < 0) {
            throw new IllegalArgumentException("number requested cannot be negative: " + n);
        }

        // if producer is set then we will request from it
        // otherwise we increase the requested count by n
        Producer producerToRequestFrom;
        synchronized (this) {
            if (producer != null) {
                producerToRequestFrom = producer;
            } else {
                addToRequested(n);
                return;
            }
        }
        // after releasing lock (we should not make requests holding a lock)
        producerToRequestFrom.request(n);
    }

    private void addToRequested(long n) {
        if (requested == NOT_SET) {
            requested = n;
        } else {
            final long total = requested + n;
            // check if overflow occurred
            if (total < 0) {
                requested = Long.MAX_VALUE;
            } else {
                requested = total;
            }
        }
    }

    /**
     * If other subscriber is set (by calling constructor
     * {@link #Subscriber(Subscriber)} or
     * {@link #Subscriber(Subscriber, boolean)}) then this method calls
     * <code>setProducer</code> on the other subscriber. If the other subscriber
     * is not set and no requests have been made to this subscriber then
     * <code>p.request(Long.MAX_VALUE)</code> is called. If the other subscriber
     * is not set and some requests have been made to this subscriber then
     * <code>p.request(n)</code> is called where n is the accumulated requests
     * to this subscriber.
     *
     * @param p
     *            producer to be used by this subscriber or the other subscriber
     *            (or recursively its other subscriber) to make requests from
     */
    public void setProducer(Producer p) {
        long toRequest;
        boolean passToSubscriber = false;
        synchronized (this) {
            toRequest = requested;
            producer = p;
            if (subscriber != null) {
                // middle operator ... we pass through unless a request has been made
                if (toRequest == NOT_SET) {
                    // we pass through to the next producer as nothing has been requested
                    passToSubscriber = true;
                }
            }
        }
        // do after releasing lock
        if (passToSubscriber) {
            subscriber.setProducer(producer);
        } else {
            // we execute the request with whatever has been requested (or Long.MAX_VALUE)
            if (toRequest == NOT_SET) {
                producer.request(Long.MAX_VALUE);
            } else {
                producer.request(toRequest);
            }
        }
    }
}

通过读源码可知Subscriber实现了 Observer接口,毫无疑问,Subscriber是一个观察者,Observer源码如下,简单易懂,这里不多说,看不懂的可以看另一篇
Android中的RxJava

public interface Observer<T> {

    /**
     * Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
     * <p>
     * The {@link Observable} will not call this method if it calls {@link #onError}.
     */
    void onCompleted();

    /**
     * Notifies the Observer that the {@link Observable} has experienced an error condition.
     * <p>
     * If the {@link Observable} calls this method, it will not thereafter call {@link #onNext} or
     * {@link #onCompleted}.
     *
     * @param e
     *          the exception encountered by the Observable
     */
    void onError(Throwable e);

    /**
     * Provides the Observer with a new item to observe.
     * <p>
     * The {@link Observable} may call this method 0 or more times.
     * <p>
     * The {@code Observable} will not call this method again after it calls either {@link #onCompleted} or
     * {@link #onError}.
     *
     * @param t
     *          the item emitted by the Observable
     */
    void onNext(T t);

}

首先Subscriber是一个抽象类,所以不能直接使用,又实现了Subscription接口,那么这个Subscription是干什么的呢,源码也不多,贴上

/**
 * Subscription returns from {@link Observable#subscribe(Subscriber)} to allow unsubscribing.
 * <p>
 * See the utilities in {@link Subscriptions} and the implementations in the {@code rx.subscriptions} package.
 * <p>
 * This interface is the RxJava equivalent of {@code IDisposable} in Microsoft's Rx implementation.
 */
public interface Subscription {

    /**
     * Stops the receipt of notifications on the {@link Subscriber} that was registered when this Subscription
     * was received.
     * <p>
     * This allows deregistering an {@link Subscriber} before it has finished receiving all events (i.e. before
     * onCompleted is called).
     */
    void unsubscribe();

    /**
     * Indicates whether this {@code Subscription} is currently unsubscribed.
     *
     * @return {@code true} if this {@code Subscription} is currently unsubscribed, {@code false} otherwise
     */
    boolean isUnsubscribed();

}

Subscription翻译成中文是名词订阅的意思,在 执行 Observable.subscribe(Subscriber);后return的对象就是一个Subscription;
Subscription 一共两个方法 ,unsubscribe()允许订阅后取消订阅,isUnsubscribed()判断是否已经取消了订阅。Subscription搞完了我们继续回到Subscriber源代码。
Subscriber一共有三个构造方法

 protected Subscriber() {
        this(null, false);
    }

    /**
     * Construct a Subscriber by using another Subscriber for backpressure and
     * for holding the subscription list (when <code>this.add(sub)</code> is
     * called this will in fact call <code>subscriber.add(sub)</code>).
     *
     * @param subscriber
     *            the other Subscriber
     */
    protected Subscriber(Subscriber<?> subscriber) {
        this(subscriber, true);
    }

    /**
     * Construct a Subscriber by using another Subscriber for backpressure and
     * optionally for holding the subscription list (if
     * <code>shareSubscriptions</code> is <code>true</code> then when
     * <code>this.add(sub)</code> is called this will in fact call
     * <code>subscriber.add(sub)</code>).
     * <p>
     * To retain the chaining of subscribers when setting
     * <code>shareSubscriptions</code> to <code>false</code>, add the created
     * instance to {@code subscriber} via {@link #add}.
     *
     * @param subscriber
     *            the other Subscriber
     * @param shareSubscriptions
     *            {@code true} to share the subscription list in {@code subscriber} with
     *            this instance
     * @since 1.0.6
     */
    protected Subscriber(Subscriber<?> subscriber, boolean shareSubscriptions) {
        this.subscriber = subscriber;
        this.subscriptions = shareSubscriptions && subscriber != null ? subscriber.subscriptions : new SubscriptionList();
    }

前来两个构造最后都会调用第三个,直接看第三个构造方法,Subscriber(Subscriber<?> subscriber, boolean shareSubscriptions)需要两个参数,subscriber毫无疑问是一个观察者,并赋值给了 this.subscriber, 那么shareSubscriptions是什么鸟东西呢

        this.subscriptions = shareSubscriptions && subscriber != null ? subscriber.subscriptions : new SubscriptionList();

通过上面代码逻辑知道,只有当shareSubscriptions为true和subscriber不为空时, this.subscriptions才会使用传入的subscriber.subscriptions,否则new 个SubscriptionList,SubscriptionList又是什么呢,SubscriptionList也是一个Subscription ,内部还有一个Subscription list可以unsubscribed together,剩下的就是对内部list增删改查操作


/**
 * Subscription that represents a group of Subscriptions that are unsubscribed together.
 *
 * @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.disposables.compositedisposable(v=vs.103).aspx">Rx.Net equivalent CompositeDisposable</a>
 */
public final class SubscriptionList implements Subscription {

    private List<Subscription> subscriptions;
    private volatile boolean unsubscribed;

    /**
     * Constructs an empty SubscriptionList.
     */
    public SubscriptionList() {
        // nothing to do
    }

    /**
     * Constructs a SubscriptionList with the given initial child subscriptions.
     * @param subscriptions the array of subscriptions to start with
     */
    public SubscriptionList(final Subscription... subscriptions) {
        this.subscriptions = new LinkedList<Subscription>(Arrays.asList(subscriptions));
    }

    /**
     * Constructs a SubscriptionList with the given initial child subscription.
     * @param s the initial subscription instance
     */
    public SubscriptionList(Subscription s) {
        this.subscriptions = new LinkedList<Subscription>();
        this.subscriptions.add(s);
    }

    @Override
    public boolean isUnsubscribed() {
        return unsubscribed;
    }

    /**
     * Adds a new {@link Subscription} to this {@code SubscriptionList} if the {@code SubscriptionList} is
     * not yet unsubscribed. If the {@code SubscriptionList} <em>is</em> unsubscribed, {@code add} will
     * indicate this by explicitly unsubscribing the new {@code Subscription} as well.
     *
     * @param s
     *          the {@link Subscription} to add
     */
    public void add(final Subscription s) {
        if (s.isUnsubscribed()) {
            return;
        }
        if (!unsubscribed) {
            synchronized (this) {
                if (!unsubscribed) {
                    List<Subscription> subs = subscriptions;
                    if (subs == null) {
                        subs = new LinkedList<Subscription>();
                        subscriptions = subs;
                    }
                    subs.add(s);
                    return;
                }
            }
        }
        // call after leaving the synchronized block so we're not holding a lock while executing this
        s.unsubscribe();
    }

    public void remove(final Subscription s) {
        if (!unsubscribed) {
            boolean unsubscribe;
            synchronized (this) {
                List<Subscription> subs = subscriptions;
                if (unsubscribed || subs == null) {
                    return;
                }
                unsubscribe = subs.remove(s);
            }
            if (unsubscribe) {
                // if we removed successfully we then need to call unsubscribe on it (outside of the lock)
                s.unsubscribe();
            }
        }
    }

    /**
     * Unsubscribe from all of the subscriptions in the list, which stops the receipt of notifications on
     * the associated {@code Subscriber}.
     */
    @Override
    public void unsubscribe() {
        if (!unsubscribed) {
            List<Subscription> list;
            synchronized (this) {
                if (unsubscribed) {
                    return;
                }
                unsubscribed = true;
                list = subscriptions;
                subscriptions = null;
            }
            // we will only get here once
            unsubscribeFromAll(list);
        }
    }

    private static void unsubscribeFromAll(Collection<Subscription> subscriptions) {
        if (subscriptions == null) {
            return;
        }
        List<Throwable> es = null;
        for (Subscription s : subscriptions) {
            try {
                s.unsubscribe();
            } catch (Throwable e) {
                if (es == null) {
                    es = new ArrayList<Throwable>();
                }
                es.add(e);
            }
        }
        Exceptions.throwIfAny(es);
    }
    /* perf support */
    public void clear() {
        if (!unsubscribed) {
            List<Subscription> list;
            synchronized (this) {
                list = subscriptions;
                subscriptions = null;
            }
            unsubscribeFromAll(list);
        }
    }
    /**
     * Returns true if this composite is not unsubscribed and contains subscriptions.
     * @return {@code true} if this composite is not unsubscribed and contains subscriptions.
     */
    public boolean hasSubscriptions() {
        if (!unsubscribed) {
            synchronized (this) {
                return !unsubscribed && subscriptions != null && !subscriptions.isEmpty();
            }
        }
        return false;
    }
}

下面回到Subscriber分析,Subscriber的add,unsubscribe,isUnsubscribed也都是对
Subscriber内部的SubscriptionList对象subscriptions的add,unsubscribe,isUnsubscribed操作。
Subscriber内部还有一个producer对象,最后面还没分析的三个函数都涉及到这个对象。

/**
 * Interface that establishes a request-channel between an Observable and a Subscriber and allows
 * the Subscriber to request a certain amount of items from the Observable (otherwise known as
 * backpressure).
 *
 * <p>The request amount only affects calls to {@link Subscriber#onNext(Object)}; onError and onCompleted may appear without
 * requests.
 *
 * <p>However, backpressure is somewhat optional in RxJava 1.x and Subscribers may not
 * receive a Producer via their {@link Subscriber#setProducer(Producer)} method and will run
 * in unbounded mode. Depending on the chain of operators, this can lead to {@link rx.exceptions.MissingBackpressureException}.
 */
public interface Producer {

    /**
     * Request a certain maximum number of items from this Producer. This is a way of requesting backpressure.
     * To disable backpressure, pass {@code Long.MAX_VALUE} to this method.
     * <p>
     * Requests are additive but if a sequence of requests totals more than {@code Long.MAX_VALUE} then
     * {@code Long.MAX_VALUE} requests will be actioned and the extras <i>may</i> be ignored. Arriving at
     * {@code Long.MAX_VALUE} by addition of requests cannot be assumed to disable backpressure. For example,
     * the code below may result in {@code Long.MAX_VALUE} requests being actioned only.
     *
     * <pre>
     * request(100);
     * request(Long.MAX_VALUE-1);
     * </pre>
     *
     * @param n the maximum number of items you want this Producer to produce, or {@code Long.MAX_VALUE} if you
     *          want the Producer to produce items at its own pace
     * @throws IllegalArgumentException if the request amount is negative
     */
    void request(long n);

}

Producer是一个接口,内部只有一个 void request(long n) 方法,这里就开始提到了backpressure 也就是背压的概念。在Observable和Subscriber之间建立请求通道,并允许Subscriber从Observable请求一定数量的项目(也称为背压)。请求量仅影响对Subscriber.onNext(Object)的调用;onError和onCompleted可能在没有请求的情况下出现。给request方法传递参数Long.MAX_VALUE可以理解为禁用背压,
request(100);理解为开启背压,观察者向事件发射源请求100条数据。最后谁会实现Producer接口我们先不去管它 继续往下看。

再回到 Subscriber 我们看 request(n)方法

    protected final void request(long n) {
        if (n < 0) {
            throw new IllegalArgumentException("number requested cannot be negative: " + n);
        }

        // if producer is set then we will request from it
        // otherwise we increase the requested count by n
        Producer producerToRequestFrom;
        synchronized (this) {
            if (producer != null) {
                producerToRequestFrom = producer;
            } else {
                addToRequested(n);
                return;
            }
        }
        // after releasing lock (we should not make requests holding a lock)
        producerToRequestFrom.request(n);
    }

传入的n肯定是要从数据源请求的数据数量,最大值为Long.MAX_VALUE,超过最大值的数据可能会丢弃掉,如果设置了producer,则调用producer的request方法请求数据,反之,则根据n调用 addToRequested()设置requested变量,requested没set过,则直接赋值为n,set过则大小增加n,最后判断是否大于上限Long.MAX_VALUE。

    private void addToRequested(long n) {
        if (requested == NOT_SET) {
            requested = n;
        } else {
            final long total = requested + n;
            // check if overflow occurred
            if (total < 0) {
                requested = Long.MAX_VALUE;
            } else {
                requested = total;
            }
        }
    }

剩下最后一个方法 setProducer

    public void setProducer(Producer p) {
        long toRequest;
        boolean passToSubscriber = false;
        synchronized (this) {
            toRequest = requested;
            producer = p;
            if (subscriber != null) {
                // middle operator ... we pass through unless a request has been made
                if (toRequest == NOT_SET) {
                    // we pass through to the next producer as nothing has been requested
                    passToSubscriber = true;
                }
            }
        }
        // do after releasing lock
        if (passToSubscriber) {
            subscriber.setProducer(producer);
        } else {
            // we execute the request with whatever has been requested (or Long.MAX_VALUE)
            if (toRequest == NOT_SET) {
                producer.request(Long.MAX_VALUE);
            } else {
                producer.request(toRequest);
            }
        }
    }

不论subscriber是否有被set过,producer都会被赋值,如果subscriber有被set过且request未被调用过,会执行 producer.request(Long.MAX_VALUE);反之,如果subscriber未set且request有被调用过会执行 producer.request(toRequest);
虽然能读懂Subscriber源码含义,但是单独看是没什么用,也要结合Rxjava整体调用来看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值