RxJava2.0笔记记录(一)

来源:互联网 发布:java压缩包文件名乱码 编辑:程序博客网 时间:2024/06/05 22:58

一 基本使用

Observable创建

Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {     @Override     public void subscribe(ObservableEmitter<Integer> e) throws Exception {         //ObservableEmitter 发射器的意思,用来发出事件的,它可以发出三种类型的事件,通过调用emitter的onNext(T value)、onComplete()和onError(Throwable error)就可以分别发出next事件、complete事件和error事件。     } });

Observer创建

Observer<Integer> observer = new Observer<Integer>(){  @Override  public void onSubscribe(Disposable d) {  //开关的意思,当调用它的dispose()方法时,它就会切断事件的接受,导致观察者接受不到事件。这个可以用作当页面销毁时,取消网络请求。  }  @Override  public void onNext(Integer integer) {       }  @Override  public void onError(Throwable e) {  }  @Override  public void onComplete() {  }};

订阅被观察者与观察者

observable.subscribe(observer);

一个observable可能没有观察者订阅,也可以多个观察者订阅,当观察者和被观察者建立联系后,被观察者可以通过onNext发送事件,也可以发送onComplete标志事件完成,被观察者发送onComplete之后,可以继续发送,而观察者接受到onComplete之后,就不会继续接收事件。

onComplete和onError必须唯一并且互斥。

subscribe有多个方法的重载,带有一个参数的Consumer方法,表示下游可以只关心onNext方法。


二 线程控制

默认情况下,观察者和被观察者工作在主线程。通常我们的需求是在子线程做耗时操作,然后回到主线程中来操作UI。此时我们可以用线程控制来达到这一目的。

observable     .subscribeOn(Schedulers.io())  //subscribeOn被观察者工作的线程     .observeOn(AndroidSchedulers.mainThread()) //observeOn 观察者工作的线程     .subscribe(observer);

RxJava内置线程选项:
1.Schedulers.io() 代表io操作的线程, 通常用于网络,读写文件等io密集型的操作,内部用线程池维护。
2.Schedulers.computation() 代表CPU计算密集型的操作, 例如需要大量计算的操作
3.Schedulers.newThread() 代表一个常规的新线程
4.AndroidSchedulers.mainThread() 代表Android的主线程

注意:
1.多次指定被观察者的线程只有第一次指定的有效, 也就是说多次调用subscribeOn() 只有第一次的有效, 其余的会被忽略.
2.多次指定观察者的线程是可以的, 也就是说每调用一次observeOn() , 下游的线程就会切换一次.


三 操作符

< 1 >.map

map是RxJava中最简单的一个变换操作符, 它的作用就是对observable发送的每一个事件应用一个函数, 使得每一个事件都按照指定的函数去变化.

eg:

Observable.create(new ObservableOnSubscribe<Integer>() {    @Override    public void subscribe(ObservableEmitter<Integer> e) throws Exception {        e.onNext(1);        e.onNext(2);        e.onNext(3);    }}).map(new Function<Integer, String>() {    @Override    public String apply(Integer integer) throws Exception {        return "this is " + integer;    }}).subscribeOn(Schedulers.io())  .observeOn(AndroidSchedulers.mainThread())  .subscribe(new Consumer<String>() {      @Override      public void accept(String s) throws Exception {          System.out.println(s);      }  });

通过Map可以将Observable发送的事件转换为任意的类型。

< 2 >. flatmap

FlatMap将一个发送事件的Observable变换为多个发送事件的Observables,然后将它们发射的事件合并后放进一个单独的Observable里.

eg:

Observable.create(new ObservableOnSubscribe<Integer>() {        @Override        public void subscribe(ObservableEmitter<Integer> e) throws Exception {            e.onNext(1);            e.onNext(2);            e.onNext(3);        }    }).flatMap(new Function<Integer, ObservableSource<String>>() {        @Override        public ObservableSource<String> apply(Integer integer) throws Exception {            List<String> list = new ArrayList<>();            for(int i = 0; i<3; i++){                list.add("I am value " + integer);            }            return Observable.fromIterable(list).delay(10, TimeUnit.MILLISECONDS);        }    }).subscribe(new Consumer<String>() {        @Override        public void accept(String s) throws Exception {            System.out.println(s);        }    });

注意:flatmap并不能保证事件的顺序,如果需要保证事件的顺序可以使用concatmap,用法和flatmap一样。

< 3 >.zip

zip通过一个函数将多个Observable发送的事件结合到一起,然后发送这些组合到一起的事件. 它按照严格的顺序应用这个函数。它只发射与发射数据项最少的那个Observable一样多的数据。

Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() {    @Override    public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {    }}).subscribeOn(Schedulers.io());Observable<String> observable2 = Observable.create(new ObservableOnSubscribe<String>() {    @Override    public void subscribe(ObservableEmitter<String> emitter) throws Exception {    }}).subscribeOn(Schedulers.io());Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {    @Override    public String apply(Integer integer, String s) throws Exception {        return "";    }}).subscribe(new Consumer<String>() {    @Override    public void accept(String s) throws Exception {    }});

四. 背压 Backpressure

< 1 >.原理引入

当observable和observer工作在不同线程时,它们之间不能直接通信,当observable发送一个事件时,是放在一个容器(具体就是一个队列)里面的,当容器里面有事件时,才会向observer发送事件。而当observable发送事件太快,observer取事件太慢,容器就会一直放事件,最后会因为容器事件越来越多,最后导致容器OOM了。

这种observable产生事件的速度很快,而observer处理很慢,事件会堆积起来,最终挤爆你的内存,导致程序崩溃(MissingBackpressureException异常)。

至此,就可以引出背压(Backpressure)的概念:背压是指在异步场景中,被观察者发送事件速度远快于观察者的处理速度的情况下,一种告诉上游的被观察者降低发送速度的策略。

关于背压,可以看这里

< 2 >.解决方案

a. 使用filter过滤掉不需要的数据
b. 使用sample每隔一段时间从observable取出事件,发送给下游。
c. 延时降低observable发送事件的速度。
d.使用flowable解决。

大致就是从数量速度上解决。


五.Flowable

这里把被观察者指定为flowable,观察者指定为subscriber。

eg:

Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {        @Override        public void subscribe(FlowableEmitter<Integer> e) throws Exception {                }        //流速不均匀直接抛异常    }, BackpressureStrategy.ERROR);    Subscriber<Integer> subscriber = new Subscriber<Integer>() {        @Override        public void onSubscribe(Subscription s) {                 }        @Override        public void onNext(Integer integer) {        }        @Override        public void onError(Throwable t) {        }        @Override        public void onComplete() {        }    };    flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);

和observable不同的是,这里增加了一个参数,用来处理上下游流速不均衡的时候应该怎么处理的办法,在例子中直接抛出了一个BackpressureStrategy.ERROR异常,也就是MissingBackpressureException异常。同时观察者中不是再使用Disposable,而是使用Subscription,与Disposable不同的是,这种采用的是响应式拉取,当在onSubscribe方法中调用了request方法时,observable会根据request的事件数量发相应数量的事件。observable不会再一直发事件。如果不调用request方法,在同一线程,就会抛MissingBackpressureException异常,在不同线程,observable就会先把事件放到一个容器,大小为128。当observer调用request才会发送事件。


参考

1.Season_zlc的“水管”系列
2.系列文章

原创粉丝点击