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
形式的接口 (例如 Action2
, Action3
) 的,它们可以被用以包装不同的无返回值的方法。<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最神奇的地方之一就是线程程的切换,碉堡了,随意切换线程,想想都爽。
- Rxjava源码(一)
- 源码阅读--RxJava(一)
- Rxjava源码浅析(一)观察者模式
- RxJava源码分析(一)
- RxJava结合源码学习一
- 深入浅出--Rxjava源码分析<一>
- 深入解析RxJava源码(一)Observable对象的构建
- 理解RxJava(一)基本流程源码分析
- RxJava教程(一)
- Rxjava要素(一)
- RxJava使用(一)
- RxJava 初探(一)
- 王学岗RxJava(一)
- RxJava 学习(一)
- RxJava从零开始(一)
- RxJava学习(一)
- RXjava学习(一)
- RxJava入门(一)
- gulp初探——前端开发工作流
- IONIC----08.route_menu_tab
- instanceof
- 探索Settings.System.putInt()
- NYOJ-476谁是英雄,分解质因子求约数个数!
- Rxjava源码(一)
- 【android】安卓手机连接电脑时候adb devices找不到设备及找到设备但无权限的问题
- C++的继承相关知识
- gw_Disjoint Set (并查集) 模板及拓展应用
- Java中的多线程编程相关基础知识
- Charts框架
- 这个问题不会答,跳槽怎么成?
- tjut 3792
- linux下用户使用sql*plus的环境配置