RxJava2.0笔记记录(一)

一 基本使用

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.系列文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值