浅析RxJava核心

浅析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例子:

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);
    }
}

      最后会Toast出1,2,3。

/这是一条华丽的分割线///

首先,我们先分析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之前的ObservableonSubscribe(我当时看到这里也是感到深深的不适),然后这个旧的onSubscribe调用新的subscriberonNextonComplete等方法
                          //后来总结了下,用代理模式的眼光看这里的代码会更容易理解一些
                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,本文难免有疏漏,请多多指教!











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值