Rxjava源码(一)

来源:互联网 发布:linux转发工具 编辑:程序博客网 时间:2024/05/21 20:46

还是先说一下RxJava是啥吧

一个词:异步

RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava ,概括得非常精准。

其实, RxJava 的本质可以压缩为异步这一个词。说到根上,它就是一个实现异步操作的库,而别的定语都是基于这之上的。

那他好在哪里,为什么异步非要用它,不用handler,AsyncTask。。。。。。

还是一个字:简洁

异步操作很关键的一点是程序的简洁性,因为在调度过程比较复杂的情况下,异步代码经常会既难写也难被读懂。 Android 创造的 AsyncTask 和Handler ,其实都是为了让异步代码更加简洁。RxJava 的优势也是简洁,但它的简洁的与众不同之处在于,随着程序逻辑变得越来越复杂,它依然能够保持简洁。把什么复杂逻辑都能穿成一条线的简洁。


RxJava有四个基本概念

Observable(被观察者)Observer(观察者) subscribe(订阅) 和事件,

先看Observable

public class Observable<T> {    final OnSubscribe<T> onSubscribe;    /**     * Creates an Observable with a Function to execute when it is subscribed to.     * <p>     * <em>Note:</em> Use {@link #create(OnSubscribe)} to create an Observable, instead of this constructor,     * unless you specifically have a need for inheritance.     *      * @param f     *            {@link OnSubscribe} to be executed when {@link #subscribe(Subscriber)} is called     */    protected Observable(OnSubscribe<T> f) {        this.onSubscribe = f;    }    private static final RxJavaObservableExecutionHook hook = RxJavaPlugins.getInstance().getObservableExecutionHook();    /**     * Returns an Observable that will execute the specified function when a {@link Subscriber} subscribes to     * it.     */    public final static <T> Observable<T> create(OnSubscribe<T> f) {        return new Observable<T>(hook.onCreate(f));    }    /**     * Invoked when Observable.subscribe is called.     */    public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {        // cover for generics insanity    }</span></span>

从源码可以看到,创建一个Observable对象,需要调用它的create().这个函数需要一个OnSubcsribe对象作为参数,该参数被保存在Observable的属性中,OnSubcsribe是一个接口对象,Observable的subscribe方法被调用的时候回触发他。这样实现了不订阅不发事件,只有订阅产生才发事件,这也是跟广播不一样的地方。

关于创建一个Observable对象还有几种方式:

public final static <T> Observable<T> from(T[] array) {        return from(Arrays.asList(array));    }

ublic final static <T> Observable<T> just(final T value) {        return ScalarSynchronousObservable.create(value);    }

注意一下找个just的方法,稍微记住一下。后边会出现找个跟别人不一样的东西。

第二个概念就是Observer,即观察者,决定事件触发的时候有怎样的行为,他就是一个接口,看一下源码

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);}</span></span>
但是Observer对象在被使用的时候也是先转化为SubScriber对象,我们来看看关于Subscriber的源码

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 = null;        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 thru unless a request has been made                if (toRequest == NOT_SET) {                    // we pass-thru 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);            }        }    }}</span></span>


下面再来看看subscribe()方法。最常见的:

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">/**     * Subscribes to an Observable and provides an Observer that implements functions to handle the items the     * Observable emits and any error or completion notification it issues.     * <dl>     *  <dt><b>Scheduler:</b></dt>     *  <dd>{@code subscribe} does not operate by default on a particular {@link Scheduler}.</dd>     * </dl>     *     * @param observer     *             the Observer that will handle emissions and notifications from the Observable     * @return a {@link Subscription} reference with which the {@link Observer} can stop receiving items before     *         the Observable has completed     * @see <a href="http://reactivex.io/documentation/operators/subscribe.html">ReactiveX operators documentation: Subscribe</a>     */    public final Subscription subscribe(final Observer<? super T> observer) {        if (observer instanceof Subscriber) {            return subscribe((Subscriber<? super T>)observer);        }        return subscribe(new Subscriber<T>() {            @Override            public void onCompleted() {                observer.onCompleted();            }            @Override            public void onError(Throwable e) {                observer.onError(e);            }            @Override            public void onNext(T t) {                observer.onNext(t);            }        });    }</span></span>
可以看到,Observer对象会被转化为Subscriber对象,继续追到下一步

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">public final Subscription subscribe(Subscriber<? super T> subscriber) {        return Observable.subscribe(subscriber, this);    }</span></span>
next

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">   private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {     // validate and proceed        if (subscriber == null) {            throw new IllegalArgumentException("observer can not be null");        }        if (observable.onSubscribe == null) {            throw new IllegalStateException("onSubscribe function can not be null.");            /*             * the subscribe function can also be overridden but generally that's not the appropriate approach             * so I won't mention that in the exception             */        }                // new Subscriber so onStart it        subscriber.onStart();                /*         * See https://github.com/ReactiveX/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls         * to user code from within an Observer"         */        // if not already wrapped        if (!(subscriber instanceof SafeSubscriber)) {            // assign to `observer` so we return the protected version            subscriber = new SafeSubscriber<T>(subscriber);        }        // The code below is exactly the same an unsafeSubscribe but not used because it would add a sigificent depth to alreay huge call stacks.        try {            // allow the hook to intercept and/or decorate            hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);            return hook.onSubscribeReturn(subscriber);        } catch (Throwable e) {            // special handling for certain Throwable/Error/Exception types            Exceptions.throwIfFatal(e);            // if an unhandled error occurs executing the onSubscribe we will propagate it            try {                subscriber.onError(hook.onSubscribeError(e));            } catch (OnErrorNotImplementedException e2) {                // special handling when onError is not implemented ... we just rethrow                throw e2;            } catch (Throwable e2) {                // if this happens it means the onError itself failed (perhaps an invalid function implementation)                // so we are unable to propagate the error correctly and will just throw                RuntimeException r = new RuntimeException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);                // TODO could the hook be the cause of the error in the on error handling.                hook.onSubscribeError(r);                // TODO why aren't we throwing the hook's return value.                throw r;            }            return Subscriptions.unsubscribed();        }    }</span></span>

总体来说,这个方法好像就做了三件事情:

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">publicSubscription subscribe(Subscriber subscriber){ subscriber.onStart();onSubscribe.call(subscriber); return subscriber;}</span></span>

除了 subscribe(Observer) 和 subscribe(Subscriber) ,subscribe() 还支持不完整定义的回调,RxJava 会自动根据定义创建出 Subscriber 。

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">public final Subscription subscribe(final Action1<? super T> onNext) {        if (onNext == null) {            throw new IllegalArgumentException("onNext can not be null");        }        return subscribe(new Subscriber<T>() {            @Override            public final void onCompleted() {                // do nothing            }            @Override            public final void onError(Throwable e) {                throw new OnErrorNotImplementedException(e);            }            @Override            public final void onNext(T args) {                onNext.call(args);            }        });    }</span></span>

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError) {        if (onNext == null) {            throw new IllegalArgumentException("onNext can not be null");        }        if (onError == null) {            throw new IllegalArgumentException("onError can not be null");        }        return subscribe(new Subscriber<T>() {            @Override            public final void onCompleted() {                // do nothing            }            @Override            public final void onError(Throwable e) {                onError.call(e);            }            @Override            public final void onNext(T args) {                onNext.call(args);            }        });    }</span></span>

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">public final Subscription subscribe(final Action1<? super T> onNext, final Action1<Throwable> onError, final Action0 onComplete) {        if (onNext == null) {            throw new IllegalArgumentException("onNext can not be null");        }        if (onError == null) {            throw new IllegalArgumentException("onError can not be null");        }        if (onComplete == null) {            throw new IllegalArgumentException("onComplete can not be null");        }        return subscribe(new Subscriber<T>() {            @Override            public final void onCompleted() {                onComplete.call();            }            @Override            public final void onError(Throwable e) {                onError.call(e);            }            @Override            public final void onNext(T args) {                onNext.call(args);            }        });    }</span></span>

Action0 是 RxJava 的一个接口,它只有一个方法 call(),这个方法是无参无返回值的;由于 onCompleted() 方法也是无参无返回值的,因此 Action0 可以被当成一个包装对象,将 onCompleted() 的内容打包起来将自己作为一个参数传入 subscribe() 以实现不完整定义的回调。这样其实也可以看做将 onCompleted() 方法作为参数传进了 subscribe()

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">public interface Action0 extends Action {    void call();}</span></span>

Action1 也是一个接口,它同样只有一个方法 call(T param),这个方法也无返回值,但有一个参数;与 Action0 同理,由于 onNext(T obj) 和 onError(Throwable error) 也是单参数无返回值的,因此 Action1 可以将 onNext(obj) 和 onError(error) 打包起来传入 subscribe() 以实现不完整定义的回调。事实上,虽然 Action0 和 Action1 在 API 中使用最广泛,但 RxJava 是提供了多个 ActionX 形式的接口 (例如 Action2Action3) 的,它们可以被用以包装不同的无返回值的方法。

<span style="font-family:SimHei;font-size:14px;"><span style="font-family:SimHei;font-size:14px;">public interface Action1<T> extends Action {    void call(T t);}</span></span>
目前可以可以简单完成一次RxJava的使用,事件的发出和消费都是在同一个线程,这实现的只是一个同步的观察者模式,然而,这并没有什么卵用,RxJava最神奇的地方之一就是线程程的切换,碉堡了,随意切换线程,想想都爽。

0 0
原创粉丝点击