RxJava学习笔记

262 阅读7分钟

中文文档   mcxiaoke.gitbooks.io/rxdocs/

Github地址   github.com/ReactiveX/R…

一. RxJava的作用、能解决的问题:

  • 线程切换
  • 数据流处理,map、transform等

一句话总结:使用可观察数据流进行异步编程

二. 基础概念

1. Observable:被观察者

它是一个抽象类,实现接口ObservableSource,使观察者可订阅到该可观察源实例。

它支持一系列转换,所以有很多对应的方法,这是所有被观察者共有的。

为了使用方便,根据发射数据的方式,它细分出了一些常用的Observable,它们都继承自抽象类Observable,内部使用自己的发射器Emitter发射数据。

public interface ObservableSource<T> {      
    //唯一的方法,将指定的观察者订阅到该可观察源实例
    //观察者不能为空,否则会有NPE
    void subscribe(@NonNull Observer<? super T> observer);
}

public interface Emitter {

    //发射一个非空的值
    onNext(@NonNull T value)
    //发射一个非空的异常
    onError(@NonNull Throwable error)
    //一个完成的信号
    onComplete()

}

2. AbstractObservableWithUpstream

除初始Observable以外,中间的Observable流都继承自它,确保持有上游Observable的引用。(这里需要了解Rxjava将所有对Observable的操作都封装成了一个这个类的子类)

3. Observer

观察者,对事件源的操作进行响应及处理。

public interface Observer<T> { 
    //接收可中断的订阅流
    void onSubscribe(@NonNull Disposable d); 
    void onNext(@NonNull T t);  
    void onError(@NonNull Throwable e);
    void onComplete();
}

⚠️注意:onError 和 onComplete 只会执行其中一个,因为 Emitter 中 onError 和 onComplete 的时候最终都会执行dispose(),onError 和 onComplete 内容执行的条件是!isDisposed()。

4. Single

它总是只发射一个值,或者一个错误通知,而不是发射一系列的值。

Single类似于Observable,不同的是,它总是只发射一个值,或者一个错误通知,而不是发射一系列的值。

因此,不同于Observable需要三个方法onNext, onError, onCompleted,订阅Single只需要两个方法:

  • onSuccess - Single发射单个的值到这个方法
  • onError - 如果无法发射需要的值,Single发射一个Throwable对象到这个方法

Single只会调用这两个方法中的一个,而且只会调用一次,调用了任何一个方法之后,订阅关系终止。

5. Subject

它同时充当了Observer和Observable的角色。

Subject可以看成是一个桥梁或者代理,它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。

分类如下:(类型特质 : mcxiaoke.gitbooks.io/rxdocs/Subj…

  • AsyncSubject
  • BehaviorSubject
  • PublishSubject
  • ReplaySubject

三. 调度器

调度器类型效果
Schedulers.computation( )用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量
Schedulers.from(executor)使用指定的Executor作为调度器
Schedulers.immediate( )在当前线程立即开始执行任务
Schedulers.io( )用于IO密集型任务,如异步阻塞IO操作,这个调度器的线程池会根据需要增长;对于普通的计算任务,请使用Schedulers.computation();Schedulers.io( )默认是一个CachedThreadScheduler,很像一个有线程缓存的新线程调度器
Schedulers.newThread( )为每个任务创建一个新线程
Schedulers.trampoline( )当其它排队的任务完成后,在当前线程排队开始执行

四. Observable线程控制

Observable.subscribeOn(Scheduler) 指定初始被观察者的执行线程,它返回一个重新封装好的Observable oso,叫ObservableSubscribeOn。因为oso继承自Observable,所以它的执行操作也在核心方法subscribeActual中,即线程调度的操作在subscribeActual中执行。它要处理初始被观察者的执行线程,那么它一定持有初始被观察者的引用和线程调度器Scheduler的引用。ObservableSubscribeOn中subscribeActual方法如下:

@Overridepublic void subscribeActual(final Observer<? super T> observer) {    
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);    
    observer.onSubscribe(parent);  
    //注意:scheduler.scheduleDirect 进行线程控制
    parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}

final class SubscribeTask implements Runnable {    
    private final SubscribeOnObserver<T> parent;    
    SubscribeTask(SubscribeOnObserver<T> parent) {        
        this.parent = parent;    
    }    
    @Override    
    public void run() {   
        //source为初始被观察者     
        source.subscribe(parent);    
    }
}

问题1: 如果subscribeOn(Scheduler)设置多次,那究竟哪次的有效?

答案:这是一个递归的过程,observable流会先执行它的上游内容,所以最先执行初始Observable的subscribeActual。如果有设置subscribeOn(Scheduler),那么初始Observable会变成裹几层糖衣的ObservableSubscribeOn。不管糖衣有几层,最后对初始Observable进行线程控制的肯定是最里层的糖衣,即第一个设置的Scheduler。

Observable.observeOn(Scheduler) 指定观察者/下游Observable(特殊的Observer)的执行线程,它返回新的Observable ooo,叫ObservableObserveOn。Observable原本的内容不变,只是把Observer重新封装,叫ObserveOnObserver。它要处理观察者的执行线程,那么它一定持有观察者的引用和工作线程相关的引用。ObserveOnObserver实现了Observer、Runnable接口。ObservableObserveOn中subscribeActual方法如下:

@Override
protected void subscribeActual(Observer<? super T> observer) {    
    if (scheduler instanceof TrampolineScheduler) {        
        source.subscribe(observer);    
    } else {        
        Scheduler.Worker w = scheduler.createWorker();        
        source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));    
    }
}
//-----------以下是ObserveOnObserver部分代码-------------

//ObserveOnObserver中,onNext、onError、onComplete方法都会调用该方法,实现线程调度
void schedule() {    
    if (getAndIncrement() == 0) {        
        worker.schedule(this);    
    }
}

@Overridepublic void run() {    
    if (outputFused) {        drainFused();    } 
    else {        drainNormal();    }
}

嗯,顺便注意下 thread.run() 和 thread.start()

Thread thread1 = new Thread(new Runnable() {    
    @Override    
    public void run() {        
        getVal();    
    }
}, "Thread-1");

Thread thread2 = new Thread(new Runnable() {        
    @Override    
    public void run() {        
        thread1.start();     //Thread-1
        //thread1.run();       //Thread-2    }
}, "Thread-2");private static void getVal() {    
    System.out.println(Thread.currentThread().getName());   
}

总结:就近原则,subscribeOn看第一次设置的值,离原始observable最近的那行;observeOn看离observer最近的那行,observer那行代码上方最后设置的那行。

subscribeOn相当于给Observable外面裹糖衣,它内部实现全都保持不变,糖衣层进行线程调度;最终控制observable线程的是最内层的糖衣,即第一次设置的值;

observeOn相当于给Observer外面裹糖衣,它内部实现全都保持不变,糖衣层进行线程调度;最终控制observer线程的是包裹它的最内层的糖衣,即第一次设置的值,因为observable.subscribe(observer)是从下游observable递归调用到上游observable,生效的是subscribe(observer)后第一次设置的observeOn(scheduler)的值,所以真正的控制线程是subscribe(observer)对应代码行上方离它最近的observeOn那行设置的值。

五. 数据转换等处理

数据转换以map操作为例:它生成一个新的Observable,叫ObservableMap。map的作用是对上游Observable发射的数据进行处理再发送给下游Observable,所以对上游Observable而言,它就是一个Observer。

@Override
public void subscribeActual(Observer<? super U> t) {    
    //把map的功能附加到原本的observer上
    source.subscribe(new MapObserver<T, U>(t, function));
}

//-----------以下是MapObserver部分代码-------------@Override
public void onNext(T t) {    
    if (done) {        return;    }    
    if (sourceMode != NONE) {        downstream.onNext(null);        return;    }    
    U v;    
    try {  
        //此处执行map的功能      
        v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");    
    } catch (Throwable ex) {        
        fail(ex);        
        return;    
    }  
    //将转换后的数据发送给下游接收者  
    downstream.onNext(v);
}
  • Map -> transform the items emitted by an Observable by applying a function to each item

  • FlatMap -> transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable

    V.S.

    Map只是对一个Observable发送的所有数据进行一个fuction变换;

    FlatMap是将一个Observable变换到多个Observable然后再flat到一个Observable发送;

  • Zip -> combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function

  • Concat -> emit the emissions from two or more Observables without interleaving them

  • Merge -> combine multiple Observables into one by merging their emissions

V.S.

zip并不会影响多个Observable的发送时间然后依据设置的方式将返回结果组合;

Contact会依照组合的顺序依次发送Observable(第一个没有执行完,不会执行第二个Observable);

Merge会讲多个Observable合并成一个(与zip的区别因该是不会进行再变形操作)

  • Take -> emit only the first n items emitted by an Observable
  • Reduce -> apply a function to each item emitted by an Observable, sequentially, and emit the final value
  • Skip -> suppress the first n items emitted by an Observable
  • Buffer -> periodically gather items emitted by an Observable into bundles and emit these bundles rather than emitting the items one at a time
  • Replay -> ensure that all observers see the same sequence of emitted items, even if they subscribe after the Observable has begun emitting items
  • Filter -> emit only those items from an Observable that pass a predicate test

六. 总结