2017-10-26-Rxjava机制简单分析

最近有点时间来简单研究一下Rxjava原理,Rxjava基于传统的观察者模式,同样的在Rxjava观察者模式中有两个重要的角色:Observable(被观察者)、Observer(观察者)。当被观察者的数据或者状态发生改变的时候,会及时的告知观察者,而这个告知的过程就是一个订阅关系,在Rxjava中,Observable中提供subscribe方法来实现Observable和Observe的订阅关系。
Observer是一个接口,它提供了三个函数onComplete、onError、onNext。
- onComplete表示整个事件队列完结
- onError表示在事件队列处理的过程中发生了异常,并且在Observer的定义中,onComplete和onError是互斥,两者只会在同一时间调用一次
- onNext为观察者提供需要处理的事件

在平时Rxjava的使用中,我们通常不会直接去new这个Observer,而是使用它实现类Subscriber,从它的名字一目了然表示订阅者,即需要知道最终结果的那个角色。在Subscriber类定义中,它不仅实现了Observer接口,还实现了Subscription接口,它可以用来取消订阅关系,终止事件发送。

既然订阅者需要去订阅某一个事件,那这个事件是如何创建出来的?这个事件的创建是由Observeable(被观察者)创建的,它来处理这个事件整个过程最终将结果回调给Subscriber。

所以可以看出在整个Rxjava中有这么四个角色:Observable、Subscriber、subscribe(订阅关系)、事件。

用例1(create)

通过简单的事例来了解这个过程:

Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscribersuper String> subscriber) {
                StringBuilder builder = new StringBuilder();
                builder.append("Rx");
                builder.append("Java");

                subscriber.onNext(builder.toString());
                subscriber.onCompleted();
            }
        }).subscribe(new Subscriber() {
            @Override
            public void onCompleted() {
                Log.i("TAG","onCompleted");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                Log.i("TAG","==> "+s);
            }
        });

这是一个简单的用例,这里没有涉及到线程切换、事件变换等复杂的使用。从代码中看到,Observable中提供了一个create函数:

    public static  Observable create(OnSubscribe f) {
        return new Observable(RxJavaHooks.onCreate(f));
    }

在create的函数中接受一个OnSubscribe对象,这个OnSubscribe是定义在Observable中的一个接口:

    public interface OnSubscribe<T> extends Action1<Subscribersuper T>> {
        // cover for generics insanity
    }

继承了Action1,在Action1申明了一个函数call,call函数接受一个泛型T

public interface Action1<T> extends Action {
    void call(T t);
}

OnSubscribe指定了Action1中的泛型为Subscriber,所以call函数会接受一个Subscriber,那么这个Subscriber是怎么传递进来的,接着上面的事例继续跟踪源码,刚刚说到create函数里传递进来一个OnSubscribe对象,并且将这个对象作为参数传递到Observable的构造器中,在Observable的构造器中只做了一件事情:

protected Observable(OnSubscribe f) {
        this.onSubscribe = f;
 }

将外部new出来的OnSubscribe对象赋值给全局变量,至此准备工作已经做完了,在这里我觉得可以把OnSubscribe的call函数理解为被观察者要处理的事件,等到事件处理完之后需要将结果回调给Subscriber,所以在call函数中我们需要接受这一个Subscriber,调用它的onNext、onComplete、或者onError。
那么整个订阅的事件过程是通过subscribe函数展开的:

    public final Subscription subscribe(Subscribersuper T> subscriber) {
        return Observable.subscribe(subscriber, this);
    }

    static  Subscription subscribe(Subscribersuper T> subscriber, Observable observable) {
     // validate and proceed
        if (subscriber == null) {
            throw new IllegalArgumentException("subscriber 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(subscriber);
        }

        // The code below is exactly the same an unsafeSubscribe but not used because it would
        // add a significant depth to already huge call stacks.
        try {
            // allow the hook to intercept and/or decorate
            RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
            return RxJavaHooks.onObservableReturn(subscriber);
        } catch (Throwable e) {
            ...
        }
    }

在订阅关系中我们需要指明一个订阅者Subscriber,接着调用了Observable中的静态subscribe方法,在所有事件发送之前,它先调用了subscriber的onStart方法,用于做一些准备工作,然后对subscriber进行一次包装,跳过RxJavaHook的操作,先不去了解它的作用,最后可以看到它调用了Observable中之前赋值的全局变量OnSubscribe的call方法,并且将最后包装的subscriber传递进去,所以在上面的用例代码中,call函数创建一个新的String然后将这个结果通过subscriber的onNext传递过去即表示我们想要的最终结果。这个过程简单不复杂,我觉得先弄清楚基本的流程在去深入是个比较好的方法,只是我自己的见解,因为从一开始直接上来了解复杂的操作符和线程调度,会看的云里雨雾的。

用例2 (just)

再举一个常用的例子:

Observable.just("Tom","Bob","Json")
                .subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {
                        Log.i(TAG,"onCompleted ");
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.i(TAG,"item = "+s);
                    }
                });

just函数会把这3个item转换成一个Observable并将它们一一发送出去,也就是说onNext方法会调用3次,等到最后所有的事件发送完了调用onComplete来结束这个事件队列。

public static  Observable just(T t1, T t2, T t3) {
        return from((T[])new Object[] { t1, t2, t3 });
}

public static  Observable from(T[] array) {
        int n = array.length;
        if (n == 0) {
            return empty();
        } else
        if (n == 1) {
            return just(array[0]);
        }
        return create(new OnSubscribeFromArray(array));
 }

在just函数中将所有要发送的事件都存放在一个Object数组中并将这个数组传递给from,因为这里我们的length为3,所以直接调用了create方法,前面的用例1我们自己手动的去创建了一个OnSubscribe对象,在这里Rxjava帮我们创建了一个内置的OnSubscribe,可以肯定的一点就是这个OnSubscribeFromArray它是OnSubscribe的实现类,并且将它的实例对象赋值给Observable的全局变量OnSubscribe。

public final class OnSubscribeFromArray<T> implements OnSubscribe<T> {
    final T[] array;
    public OnSubscribeFromArray(T[] array) {
        this.array = array;
    }

    @Override
    public void call(Subscribersuper T> child) {
        child.setProducer(new FromArrayProducer(child, array));
    }

    //....
}

到这里同用例1一样我们的准备工作已经做完了,剩下的只是要知道是哪个订阅者需要订阅整个事件,那还是subscriber方法里传递一个Subscriber对象,同样的在subscribe方法里先是调用了onStart方法,然后调用Observable.OnSubscribe的call函数,这里的OnSubscribe就是OnSubscribeFromArray。回想到用例1的call函数里我们是自己创建一个事件然后自己手动的将结果回调给subscriber,那么在OnSubscribeFromArray的call函数中,我们并没有看到subscriber的任何回调函数,那么它是如何将事件发送出去的呢?这话说的如同放屁一般,那肯定是有办法的。
在call函数中看到有setProducer,这个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

意思就是说它用来在Observable和Subscriber之间建立一个请求通道,允许Subscriber主动的从Observable中请求一定量的item事件。也就是说整个事件发送的过程是有Producer来完成的。在Producer中只定义了一个方法:

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.
     * 

* 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 may 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. * *

     * request(100);
     * request(Long.MAX_VALUE-1);
     * 
* * @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); }

从注释中知道n表示的是发送事件队列的大小长度,最大为Long.MAX_VALUE,如果超出这个长度的话系统会自动抛出一个非法参数异常。

既然它是接口那么肯定有实现类,在OnSubscribeFromArray中定义了一个FromArrayProducer静态内部类,它实现了Producer。在call函数中会调用subscriber的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);
            }
        }
}

这个方法不太好理解,但是最终toRequest == NOT_SET 随之调用了producer.request(Long.MAX_VALUE);也就是在call函数中setProducer的时候就调用了request方法,转过头来看FromArrayProducer的request方法:

        @Override
        public void request(long n) {
            if (n < 0) {
                throw new IllegalArgumentException("n >= 0 required but it was " + n);
            }
            if (n == Long.MAX_VALUE) {
                if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
                    fastPath();
                }
            } else
            if (n != 0) {
                if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
                    slowPath(n);
                }
            }
        }

以为n从上面传递进来的是Long.MAX_VALUE所以进入到了fastPath方法中:

    void fastPath() {
            final Subscribersuper T> child = this.child;

            for (T t : array) {
                if (child.isUnsubscribed()) {
                    return;
                }

                child.onNext(t);
            }

            if (child.isUnsubscribed()) {
                return;
            }
            child.onCompleted();
        }

从FromArrayProducer的构造器中我们知道child指向Subscriber,array指向了之前的Object数组,所以可以很清楚地看到在fastPath中它for循环迭代了array,判断subscriber是否取消订阅了,如果没有就调用了subscriber的onNext方法,这里的onNext调用了3次,最后调用了onComplete结束。

抛开Rxjava的复杂的事件变换和线程切换等操作,我们可以看到观察者模式在Rxjava中的体现的还是比较的清晰,但是仅仅了解这么一点还是不够的,因为Rxjava的精髓并不在这里。这篇文章只是简单了解一下它的流程是怎么进行的。

你可能感兴趣的:(2017-10-26-Rxjava机制简单分析)