还是先说一下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最神奇的地方之一就是线程程的切换,碉堡了,随意切换线程,想想都爽。