浅析RxJava核心
RxJava是NetFlix推出的Reactive Extensions框架的Java语言实现,同时也推出了其他平台上的RxJava包括C#、Java和JavaScript等等。这里主要介绍下RxJava的核心功能和核心函数的源码实现.
官方对Rx的表述是:Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序,使用Rx,开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流, 用Schedulers参数化异步数据流的并发处理,Rx可以这样定义:Rx = Observables + LINQ + Schedulers。我自己分析的RxJava的两个核心是"异步"和"解耦"。实际上,RxJava的操作过程就是:"Observable -> Operators -> Subscriber"。其中,Observable为模型中的目标对象,Subscriber为观察者,而Operators负责目标对象发出的信息给观察者们的一个操作变化。Operators正是用来实现进行逻辑处理和线程切换的功能.
在AndroidStudio中引入RxJava:
dependencies { compile 'io.reactivex:rxjava:1.0.14' compile 'io.reactivex:rxandroid:1.0.1' }这里只讨论RxJava比较通用的功能和其背后的源码,因此这里只写出一个简单逻辑的RxJava例子:
最后会Toast出1,2,3。public class RxActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //subscriber是观察者,订阅Observable后,如果没有取消订阅,Observable会调用subscriber的方法实现观察者模式//首先回调onNext,最后是onCompleted //如果中间抛出异常,会停止传递,回调onError,这里理解起来还是很简单的。 Subscriber<Integer> subscriber = new Subscriber<Integer>() { @Override public void onCompleted() { Toast.makeText(RxActivity.this,"completed",Toast.LENGTH_SHORT).show(); } @Override public void onError(Throwable e) { Toast.makeText(RxActivity.this,"error",Toast.LENGTH_SHORT).show(); } @Override public void onNext(Integer value) { Toast.makeText(RxActivity.this,""+value,Toast.LENGTH_SHORT).show(); } }; //RxJava提供了很多创建Observable的方法,比如from将一个Iterable, 一个Future, 或者一个数组转换成一个Observable //repeat 创建一个重复发射指定数据或数据序列的Observable //repeatWhen 创建一个重复发射指定数据或数据序列的Observable,它依赖于另一个Observable发射的数据 //这里是最简单的just方法,其内部实现是create方法. Observable.just("1", "2", "3") //map方法是最基本的操作符方法,用来实现业务逻辑要求的参数的变化,也是RxJava的一个核心,其内部实现是lift方法,下文会提及 //这里是将String类型转为整形,具体的变换逻辑需要重写其中的call方法 .map(new Func1<String, Integer>() { @Override public Integer call(String value) { return Integer.valueOf(value); } }) //observeOn设定subscriber的回调操作执行在UI线程,这里就涉及到了RxJava的另一个核心"异步" //其内部实现同样是lift方法,subscribeOn则是设定业务执行逻辑执行在IO线程 //subscribeOn的内部实现和observeOn是差不多的 .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) //订阅Observable(显然这里改成subscriber.subscribe(observable)更好理解),之后会执行Subscriber的回调 .subscribe(subscriber); } }
/这是一条华丽的分割线///
首先,我们先分析Observable,它包含了1个重要的钩子(hook)RxJavaObservableExecutionHook,这个hook会在Observable创建(create),操作符变换(map)时提供对应的接口来让开发者实现自己的统一处理逻辑。除了ExecutionHook,RxJava还提供了包括RxJavaErrorHandler(需重写handlerError方法,其实和Android的CrashException很像).RxJavaSchedulersHook(对应异步处理)来实现开发者自己的需求。这3个都是原子变量,使用时都需要调用register方法注册,而且只能注册一次(疑问:为什么这3个hook都需要用反射来实现注册,直接使用单例放出来不可以吗?)
String implementingClass = System.getProperty("rxjava.plugin." + classSimpleName + ".implementation");
我们先看下整个的流程:
首先,Observable会调用just方法实例化,最底层的调用时create方法
public final static <T> Observable<T> from(Iterable<? extends T> iterable) { return create(new OnSubscribeFromIterable<T>(iterable)); }
create方法具体实现(可以在hook中加入自己的逻辑):
public final static <T> Observable<T> create(OnSubscribe<T> f) { return new Observable<T>(hook.onCreate(f)); }我们可以看到,首先实例化了OnSubscribeFromIterable,这个类实现OnSubScribe接口,重写了call方法,而这个call方法正是订阅后被回调的方法(其实OnSubScribe继承Action,call方法属于Action,但是这里只记住OnSubScribe就够了)
我们可以看到OnSubscribeFromIterable的call方法(RxJava提供了许多OnSubScribe的实现类,但是流程其实都是相似的,我们这里挑选一个有代表性的)
@Override public void call(final Subscriber<? super T> o) { final Iterator<? extends T> it = is.iterator(); if (!it.hasNext() && !o.isUnsubscribed()) o.onCompleted(); else o.setProducer(new IterableProducer<T>(o, it)); }is是Iterator变量,当迭代结束并且subscribeer(订阅者)没有取消订阅,会回调onCompleted方法;否则会设置一个producer(而不是简单地回调onNext和onError,实际上scheduler的producer更复杂,下文会提及),同样RxJava提供了接口Producer的request方法,来实现不同的业务场景IterableProducer的request方法的核心其实很简单,概括下就是onNext.
好,我们实例化完事OnSubscribeFromIterable后,回到Observable的create方法,继续执行Observale的构造方法这是简单地将OnSubScribe赋值给实例变量onSubscribe(记住这个变量,下文lift时会有大用途)
protected Observable(OnSubscribe<T> f) { this.onSubscribe = f; }执行到这里,我们先不讲map,因为理解map方法需要先理解订阅函数subscribe,我们先看下subscribe,这个函数很复杂,将核心代码抽出来以后是这样的:
subscriber.onStart(); // The code below is exactly the same an unsafeSubscribe but not used because it would add a sigificent depth to alreay huge call stacks. // allow the hook to intercept and/or decorate hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber); return hook.onSubscribeReturn(subscriber);
首先会回调subscriber的onStart方法,然后又是钩子,执行OnSubscribe的call方法,本文里是OnSubscribeFromIterable的call方法(之前已经提及)这就是大体流程。我们在看下map的流程,其底层实现是lift方法:
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) { //这里会重新new一个Observable,所以map之后的Observable已经不是原来的泛型,所以subscriber的泛型需要和最后的Observable统一 return new Observable<R>(new Observable.OnSubscribe<R>() { @Override public void call(Subscriber<? super R> o) { try { //这句话是lift的核心,hook处理过的(其实就是没处理)Operator调用call方法会产生一个新的Subscriber //但是这个新的Subscriber的泛型和map之前的Observable是一样的,原因是因为接着会再执行 onSubscribe.call(st); //注意这个onSubscribe,这是map之前的Observable的onSubscribe(我当时看到这里也是感到深深的不适),然后这个旧的onSubscribe调用新的subscriber的onNext, onComplete等方法 //后来总结了下,用代理模式的眼光看这里的代码会更容易理解一些 Subscriber<? super T> st = hook.onLift(operator).call(o); try { st.onStart(); onSubscribe.call(st); } catch (Throwable e) { if (e instanceof OnErrorNotImplementedException) { throw (OnErrorNotImplementedException) e; } st.onError(e); } } catch (Throwable e) { if (e instanceof OnErrorNotImplementedException) { throw (OnErrorNotImplementedException) e; } o.onError(e); } } }); }这是Operator的call转换方法,本文是OperatorMap类,是不是和代理模式很像?
@Override public Subscriber<? super T> call(final Subscriber<? super R> o) { return new Subscriber<T>(o) { @Override public void onCompleted() { o.onCompleted(); } @Override public void onError(Throwable e) { o.onError(e); } @Override public void onNext(T t) { try { //这里还是旧泛型,但是o已经是新泛型了 //transformer就是转换的function,只要记住主要调用它的call方法转换函数就行了 o.onNext(transformer.call(t)); } catch (Throwable e) { Exceptions.throwIfFatal(e); onError(OnErrorThrowable.addValueAsLastCause(e, t)); } } }; }
好,这是lift函数的核心,我们现在再来讲线程切换observeOn就可以轻松多了,因为observeOn的核心也是lift,只不过它的Operator是OperatorObserveOn,转换函数不同(即不同实现的call而已)。这是OperatorObserveOn的构造函数。它多了一个Scheduler,这个Scheduler是一个抽象类,RxJava为我们提供了Android专用的HandlerScheduler。Scheduler的核心是Worker,一个实现了Subscription接口的抽象类,但这里我们只需要记住Worker的另一个方法schedule即可,因为正是这个方法实现了UI线程切换。
public OperatorObserveOn(Scheduler scheduler) {
this.scheduler = scheduler;
}
还记得上文提到过,lift的核心是产生一个新的Subscriber,那么我们看看OperatorObserveOn产生一个怎样的Subscriber,ObserveOnSubscriber的构造函数,(注意其中的queue队列,到最后就是从这里面拿出的Action执行):
public ObserveOnSubscriber(Scheduler scheduler, Subscriber<? super T> child) { this.child = child; this.recursiveScheduler = scheduler.createWorker(); if (UnsafeAccess.isUnsafeAvailable()) { queue = new SpscArrayQueue<Object>(RxRingBuffer.SIZE); } else { queue = new SynchronizedQueue<Object>(RxRingBuffer.SIZE); } this.scheduledUnsubscribe = new ScheduledUnsubscribe(recursiveScheduler); }
执行构造函数的时候会执行init方法:
void init() { // don't want this code in the constructor because `this` can escape through the // setProducer call child.add(scheduledUnsubscribe); child.setProducer(new Producer() { @Override public void request(long n) { BackpressureUtils.getAndAddRequest(REQUESTED, ObserveOnSubscriber.this, n); schedule(); } }); child.add(recursiveScheduler); child.add(this); }
我们可以看到传进来的subscriber,也就是child重新设置了Producer,其中重写的request方法执行了schedule方法,而这个方法会辗转执行到HandlerScheduler的,也就是我们熟悉的handler机制,TimeUnit是一个枚举,delayTime = 0。
@Override public Subscription schedule(Action0 action, long delayTime, TimeUnit unit) { if (compositeSubscription.isUnsubscribed()) { return Subscriptions.unsubscribed(); } action = RxAndroidPlugins.getInstance().getSchedulersHook().onSchedule(action); final ScheduledAction scheduledAction = new ScheduledAction(action); scheduledAction.addParent(compositeSubscription); compositeSubscription.add(scheduledAction); handler.postDelayed(scheduledAction, unit.toMillis(delayTime)); scheduledAction.add(Subscriptions.create(new Action0() { @Override public void call() { handler.removeCallbacks(scheduledAction); } })); return scheduledAction; }
最后在scheduledAction的run方法中,会回调action的call方法,而我们传进来的action就是这个:
final Action0 action = new Action0() { @Override public void call() { pollQueue(); } };
注意,这里就使用了我们上文提到的queue变量,是一个队列的操作。至此,observeOn过程就以handler接管结束了。subscribeOn的过程和observeOn的过程类似,只是多了一个nest方法,朋友们可以自行考证。
说了这么多,其实RxJava的优越性还是没那么明显(其实RxJava对Android性能上的优化还是有限的,毕竟说到底它是一个很牛逼的设计模式,更多的是体现在可维护性可扩展性上,朋友们可以自行在AndroidStudio的Memory中验证),这里举一个业务逻辑的例子来说明RxJava的优越性:
//这是自己封装出来的一个Asyn异步框架,首先读取一张图片,然后先展现,再给图片加水印 PerspectiveFactory.getPerspectiveAsynTask(new PerspectiveAsynListener() { @Override public void onSuccess(Object o) { showBitmap(); PerspectiveFactory.getPerspectiveAsynTask(new PerspectiveAsynListener() { @Override public void onSuccess(Object o) { } @Override public void onFail(Exception e) { } @Override public Object onWork(Object[] t) { addWaterMark(); return null; } }); } @Override public void onFail(Exception e) { } @Override public Object onWork(Object[] t) { decodeBitmapFromFile(path) return null; }});如果使用RxJava,就可以这样写,高下立判:
Observable.just(path).observeOn(AndroidSchedulers.mainThread()).doOnCompleted(new Action0() { @Override public void call() { showBitmap(); } }).subscribeOn(Schedulers.io()).subscribe(new Subscriber<String>() { @Override public void onCompleted() { addWaterMark(); } @Override public void onError(Throwable e) { } @Override public void onNext(String bitmap) { decodeBitmapFromFile(path); } });
到这里,RxJava的比较通用的函数和核心代码有了一个大概的印象,其实只是冰山一角,RxJava提供了许多ObServable,Operator的不同实现,只是绝大部分的流程和本文叙述的差不多,有了一个大概的思路就很好理解其他的分支代码。RxJava是很牛逼的一个实现,里面有很多设计模式在里面,可以很好的解耦,直接降低内存泄露的可能性,对降低维护代码的成本也有作用。本人也是刚接触RxJava,本文难免有疏漏,请多多指教!