前言
本文基于:
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.1.10'
Rx回调的一些的一些小测试
在Rx中有Observer以及Observable两个对象。
Observer有onSubscribe、onNext、onError、onComplete等几个回调,分别对应订阅,事件通知,出现错误,以及事件通知完毕。这些回调都是在观察者Observer所在的线程,包括map、onErrorReturn等转换符。大致理解就是Observable在自己的工作线程吭哧吭哧的生产事件,然后将每一个生产出来的事件回调到onNext,生产错误就回调onError等,如果观察者需要对生产的事件进行自己的处理比如map,那么也应该发生在观察者所在的线程。
Observer<String> observer = new Observer<String>() { @Override public void onSubscribe(Disposable d) { SLog.i("onSubscribe"); } @Override public void onNext(String s) { SLog.i("onNext:" + s); } @Override public void onError(Throwable e) { SLog.i("onError"); } @Override public void onComplete() { SLog.i("onComplete"); } };
Observable在生产事件的时候,也许自己出现了Exception,如果没有onErrorReturn等处理错误结果,那么就直接回调onError,如果onErrorReturn中还是继续出现了Exception,那么最终还是回调onError,但是如果onErrorReturn将错误结果纠正(返回默认数据),那么就会回调onComplete,说了这么多废话,其实就是一句大家都知道的话。onError与onComplete互斥。在一次订阅周期里面只有一个会被回调。
Rx中一些其他好玩的回调
如下代码所示,可以发现多了一些好玩的回调,比如doOnSubscribe、doOnNext、doOnError、doOnComplete等,其实与上文提到的一模一样,不过这些回调都会早于响应的onXXX回调,比如doOnSubscribe > onSubscribe.
Observable .just("one", "two", "three") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnSubscribe(new Consumer<Disposable>() { @Override public void accept(Disposable disposable) throws Exception { SLog.i("doOnSubscribe"); } }) .doOnNext(new Consumer<String>() { @Override public void accept(String s) throws Exception { SLog.i("doOnNext:" + s); } }) // 这个必须写在doOnError的前面,不然不生效啊 .onErrorReturn(new Function<Throwable, String>() { @Override public String apply(Throwable throwable) throws Exception { return "default"; } }) //这个必须写,不然如果被观察者出现error,会导致程序异常 .doOnError(new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { SLog.i("doOnError"); } }) .doOnComplete(new Action() { @Override public void run() throws Exception { SLog.i("doOnComplete"); } }) .doOnTerminate(new Action() { @Override public void run() throws Exception { SLog.i("doOnTerminate"); } }) .doFinally(new Action() { @Override public void run() throws Exception { SLog.i("doFinally"); } }) .subscribe();
特别说明:
整个订阅流程必须有处理错误的回调,比如直接使用new Observer就必须实现onError,如果使用简写的Disposable subscribe(Consumer<? super T> onNext) 方法订阅,也必须实现onError。不然如果Observable出现了异常,那么会导致io.reactivex.exceptions.OnErrorNotImplementedException
Rx中的错误处理
onErrorReturn:当Observable中发生异常的时候,你有机会返回一个默认值,然后整个订阅流程就中断了,然后回调onComplete。
onErrorReturnItem:这个是onErrorReturn的一种简化形式,直接返回一个对象。
Rx常用场景一
在异步请求之前进行提示,请求完毕取消提示。
对于请求之前进行提示,我们可以在onSubscribe/doOnSubscribe中进行处理,毕竟每一次请求是从订阅开始的。
对于请求完毕取消提示,我们可能为正常结束(onComplete),也可以能出现了错误(onError),也可能是请求半路被取消掉了(取消请求不会回调onComplete/onError),所以这里就需要找一个必定回调的方法。查看源码可以发现,doOnTerminate会在onComplete、onError之前被回调,但是对于请求取消的情况不会被回调。如果想三种情况都被回调到,那么需要使用doFinally方法。
现在我们知道了onSubscribe/doOnSubscribe对应一切的开始,doFinally对应一切的结束,这样我们就可以用来控制提示的显示/隐藏了。
onSubscribe/doOnSubscribe回调在订阅的线程,如果在主线程订阅,那么这个回调就在主线程中,doFinally如果没有使用Disposable.dispose取消掉请求,那么默认和订阅发生的线程为同一线程,但是如果Disposable.dispose在另一个线程被调用,那么doFinally就在调用Disposable.dispose的线程中被回调,所以这里要注意doFinally所在的线程,不然可能在非主线程操作UI。
Rx常用技巧一
我们都知道,当使用异步操作的时候,最需要注意的就是即时的取消掉请求,不然可能导致内存泄露等情况。CompositeDisposable这个类就是Rx提供用来管理订阅的。
CompositeDisposable mCompositeDisposable = new CompositeDisposable(); //添加订阅到管理 mCompositeDisposable.add(disposable); //取消所有添加的订阅 mCompositeDisposable.dispose();
Rx常见的Exception
OnErrorNotImplementedException:这个上面已经介绍过了,主要是因为Observer没有实现onError方法,所以当Observable中出错以后没有处理错误的位置,导致Crash。
UndeliverableException:这个主要是由于Observable发送了一个事件并回调了Observer的onNext方法,可是在onNext中出现了异常,所以导致Crash。
UndeliverableException:这个主要是由于Observer取消订阅了Observable,可是Observable还在生成事件,并且在生成事件的过程中出现了一个Exception。常见的情景是Observable在进行网络请求,但是Observer取消了订阅,这时Observable出现了一个没有被catch的Exception,那么这个Exception则会导致程序Crash。
其他
其实本篇博客只是介绍了一些很小的细节,不过在开发中也是必须要清楚了解的部分,写了半天测试代码,留作笔记。