Android开发之路--Rxjava2.0的使用

文章目录

一、前言

  最近实在是被博客的格式搞的头很大,因为我都是在印象笔记中写好后再复制粘贴到博文中发表。本来在笔记中看的格式很好,一粘贴全乱了。印象笔记Mac版又不支持Markdown格式,没办法下了个有道云笔记,果然很强大。
  不多废话,我们来聊聊RxJava。Rxjava到目前已经更新到3.x版本,本文是基于2.x版本。老样子Rxjava是什么?怎么用?为什么要用?

1、RxJava是什么?

RxJava is a Java VM implementation of ReactiveX (Reactive Extensions): a library for composing asynchronous and event-based programs by using observable sequences.

简言之Rxjava就是基于观察者模式,采用事件流链式调用,用做异步处理的开发库。

2、为什么要使用Rxjava

Rxjava对于复杂的线程调用具有很大的优势,在于它的简洁性。可能对于简单的线程任务看不出它的优点,当我们面对复杂的业务逻辑时候,体现的尤为淋漓尽致。我们来重点说一下,Rxjava到底该如何使用。

二、Rxjava的使用

1、依赖配置

在build_gradle中添加依赖:

implementation "io.reactivex.rxjava2:rxjava:2.x.y"
implementation "io.reactivex.rxjava2:rxandroid:2.x.y"

注意x,y是版本号,可以在github中添加最新的依赖地址:

https://github.com/ReactiveX/RxJava/releases
https://github.com/ReactiveX/RxAndroid/releases

2、基本概念

下面说一下用到的基本概念,有助于我们理解代码及其中的原理。刚才我们提到Rxjava是基于观察者模式的。那么什么是观察者模式呢?观察者模式有点类似于生产者消费者模式,就是被观察者做出某种行为或者说产生了某种事件之后,通知给观察者继续做某些逻辑处理。举个例子:比如汽车在行驶过程中,闯红灯被电子摄像头抓怕到。汽车作为一个被观察者也就是被观察的对象,被观察者产生的事件为闯红灯,观察者为电子摄像头,当汽车在红灯的时刻驶入第二根行驶线就被判定为闯红灯,这个过程就是我们所说的观察者与被观察者。

角色作用形象
被观察者(Observable)生产事件汽车
观察者 (Observer)处理事件电子摄像头
订阅(Subscribe)连接观察者与被观察者的桥梁驶入第二根行驶线的通知

然而在android中,这种观察者模式做不到实时监控的这种状态,通常实现的机制都是,当被观察者的状态发生改变的时候通知观察者做出某种处理。这种方式都是采用注册或者是订阅的方式。接下来我们结合Rxjava的使用来介绍。

3、具体使用

++以下所说的方法在Rxjava的版本上可能有所不同,这里我使用的版本是2.2.17++

3.1 创建被观察者

创建被观察者有很多种方式,后文的4.1 创建操作符专门介绍。这里我们主要介绍通过crate()创建,方便读者理解。

 Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onNext("3");
                emitter.onComplete();
            }
        });

crate()方法创建被观察者,传入一个ObservableOnSubscribe对象,重写subscribe(),emitter对象可以理解一个事件发射器,被观察者向观察者发射事件。当被观察者被观察者订阅之后,定义的onNext()被调用三次和onComplete()就会被调用一次。create()这是Rxjava最基本创建被观察者的方法。还有两种快捷创建事件队列的方法。

被观察者发送的事件有三种:

事件类型描述
onNext()普通的事件,观察者会回调onNext()方法
onComplete()当不会有新的事件onNext()调用时,需要触
发onComplete()作为标志
onErro()异常事件,它和onComplete()是互斥的,这也就
意味着onError()和onComplete()只能调用一个。
3.2 创建观察者
Observer<String> mObserver = new Observer<String>() {

            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG,"Observer"+"onSubscribe");
            }

            @Override
            public void onNext(String s) {
                Log.d(TAG,"Observer"+s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                Log.d(TAG,"Observer"+"onComplete");
            }
        };
        
3.3 订阅
observable.subscribe(observer);

这里的写法是被观察者订阅了观察者,看起来很奇怪,其实是符合API的设计规范的。

3.4 清爽的链式调用

上面的使用显得非常繁琐,Rxjava提供了链式调用的方式

  Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onNext("3");
                emitter.onComplete();

            }}).subscribe(new Observer<String>() {

            @Override
            public void onSubscribe(Disposable d) {

            }
            @Override
            public void onNext(String s) {
                Log.e("RxJava",s);
            }
            @Override
            public void onError(Throwable e) {

            }
            @Override
            public void onComplete() {
                Log.e("RxJava","结束");
            }
        });

4、操作符

上面我们介绍了RxJava的简单使用,Rxjava更强大的地方在于它可以对被观察者向观察者发送的数据通过操作符进行处理变成我们想要的数据。下面我们来说一下常见的操作符:

4.1 创建操作符

创建操作符我们可以理解为创建被观察者的操作符。

4.1.1 create()

这种操作符我们前面已经介绍过了,不多赘述,调用的方法为

public static <T> Observable<T> create(ObservableOnSubscribe<T> source)

4.1.2 just()

有10个重载函数,通过just()创建一个被观察者并发送事件,但是发送事件的个数不能超过10个。just(T…)传入的是一个可变参数

API:

public static <T> Observable<T> just(T item) 
......
public static <T> Observable<T> just(T item1, T item2, T item3, T item4, T item5, T item6, T item7, T item8, T item9, T item10)

使用示例:

  Observable.just("1", "2", "3").subscribe(new Observer<String>() {
       @Override
       public void onSubscribe(Disposable d) {
           
       }

       @Override
       public void onNext(String s) {

       }

       @Override
       public void onError(Throwable e) {

       }

       @Override
       public void onComplete() {

       }
   });
4.1.3 from操作符

From操作被观察者模式有很多种方式,为了简便起见,后文我只写怎么创建被观察者,怎么订阅观察者就省略了。

a:fromArray操作符

API:

public static <T> Observable<T> fromArray(T... items) 

解释:fromArray创建被观察者与just方式类似传入的是一个可变参数,但是与just不同的是这个可变参数的数量可以大于10,而且可以用一个数组作为入参。其实just内部实现当参数大于等于两个的时候调用的就是fromArray()操作符。

使用示例:

//可变参数为入参
Observable<String> mObservable1 = Observable.fromArray("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10");

//数组作为入参
String[] arrays= {"1","2","3"};
Observable<String> mObservables = Observable.fromArray(arrays);

b:fromCallable操作符

API:

public static <T> Observable<T> fromCallable(Callable<? extends T> supplier) 

解释:Callable 和Runnable的用法基本一致,只是它会返回一个结果值,这个结果值就是发给观察者的。

使用示例:


Observable.fromCallable(new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return null;
    }
});
c:fromFuture操作符

API:

public static <T> Observable<T> fromFuture(Future<? extends T> future) 

解释:参数传入一个future的实现,Future 的作用是增加了 cancel() 等方法操作 Callable,它可以通过 get() 方法来获取 Callable 返回的值。

使用示例:

Observable.fromFuture(new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "1";
            }
        }));

d:fromIterable()操作符

解释:这个操作符合fromArray()类似,但是入参必须是个集合。而fromArray()的入参可以是可变参数,也可以是集合

API:

public static <T> Observable<T> fromIterable(Iterable<? extends T> source) 

使用示例

   List<String> mList = new ArrayList<>();
        mList.add("1");
        mList.add("2");
        mList.add("3");

        Observable.fromIterable(mList);

e:fromPublisher

API:

public static <T> Observable<T> fromPublisher(Publisher<? extends T> publisher)

使用示例:

Observable.fromPublisher(new Publisher<String>() {
    @Override
    public void subscribe(Subscriber<? super String> s) {
        s.onNext("1");
        s.onNext("2");
        s.onNext("3");
        s.onComplete();
    }
});

//还有一种实现方式,Flowable默认实现了Publisher接口
Flowable<String> mFlable = Flowable.create(new FlowableOnSubscribe<String>() {
        @Override
        public void subscribe(FlowableEmitter<String> emitter) throws Exception {

        }
    }, BackpressureStrategy.ERROR);
    Observable.fromPublisher(mFlable);
    
4.1.4 defer操作符

API:

public static <T> Observable<T> defer(Callable<? extends ObservableSource<? extends T>> supplier)

解释:没有立刻创建被观察者,只有当观察者订阅时才创建,并且针对观察者创建每一次订阅都是一个新的Observable。在回调里决定如何创建这个 Observable。不订阅就不创建。在call方法中需要我们返回一个Observable对象。

使用示例:

Observable.defer(new Callable<ObservableSource<String>>() {
    @Override
    public ObservableSource<String> call() throws Exception {
        return Observable.fromArray("1") ;
    }
});
4.1.5 timer操作符

API:

public static Observable<Long> timer(long delay, TimeUnit unit) ;

解释:当到指定时间后就会发送一个 0L 的值给观察者。第二个参数为时间单位。

使用示例:

 Observable.timer(2000, TimeUnit.MILLISECONDS).subscribe(new Observer<Long>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(Long aLong) {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    });
4.1.6 interval()操作符

API:

 public static Observable<Long> interval(long period, TimeUnit unit) ;
 public static Observable<Long> interval(long initialDelay, long period, TimeUnit unit);

解释:
每隔定义的时间发送一个事件,这个事件是从0开始,每次增加1的数字,initialDelay 参数,这个参数的意思就是 onSubscribe 回调之后,再次回调 onNext 的间隔时间。

使用示例:

 Observable.interval(4,TimeUnit.SECONDS).subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Long aLong) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

上述代码的意思是每隔4秒,从0开始发送事件。

4.1.7 intervalRange()操作符

API:

 public static Observable<Long> intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit);

解释:这个方法的意义与interval的意义相同,但是它可以指定发送事件的开始值和数量。第三个擦书initialDelay的意思是开始发送第一个数字的延迟值。

使用示例:

Observable.intervalRange(2,5,2,1,TimeUnit.SECONDS)
            .subscribe(new Observer<Long>() {
                @Override
                public void onSubscribe(Disposable d) {
                    
                }

                @Override
                public void onNext(Long aLong) {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });
4.1.8 range()操作符

API:

public static Observable<Integer> range(final int start, final int count);

解释:
同时发送一定范围的时间序列

使用示例:

Observable.range(0,5).subscribe(new Observer<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(Integer integer) {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    });
    
4.1.9 rangeLong()操作符

与range()操作符相比只是数据类型不同,这里不做赘述。

4.1.10 empty()&never()&erro()操作符

API:

public static <T> Observable<T> empty();
public static <T> Observable<T> never();
 public static <T> Observable<T> error(final Throwable exception);

解释:

  1. empty():直接发送onComplete()事件。
  2. never():不发送任何事件。
  3. error():发送onError()事件。
4.2 转换操作符

转换操作符的作用是将在被观察者中提供的操作符转换成观察者所需要的操作符。

4.2.1 map()操作符

API:

  public final <R> Observable<R> map(Function<? super T, ? extends R> mapper);

解释:可以将被观察者的数据类型转换为其他数据类型。
使用示例:

Observable.just(1,2,3).map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return integer.toString();
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String s) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
4.2.2 flatMap()

API:

 public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) ;

解释:
这个操作符也是对原数据的转换,比如一个年级有许多班级,每个班级有许多学生,我们需要打印每个学生的成绩可以这样做:

 Observable.fromIterable(new ArrayList<Classes>())
                .subscribe(new Observer<Classes>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Classes classes) {
                        for (Student mStudent:classes.mStudents) {
                            Log.d("Name",mStudent.getName());
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

但是我们不想在回调的时候在onNext()方法上进行遍历,因为如果逻辑复杂的情况下可能会实现多层嵌套循环才能实现,利用flatMap就很容易解决这个问题。flatMap返回的是一个Observable对象。

使用示例:


Observable.fromIterable(new ArrayList<Classes>())
      .flatMap(new Function<Classes, ObservableSource<Student>>() {
          @Override
          public ObservableSource<Student> apply(Classes classes) throws Exception {
              return Observable.fromIterable(classes.getStudents());
          }
      }).subscribe(new Observer<Student>() {
    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(Student student) {

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
});

注意:flatMap转换后发送的数据顺序可能与之前为转换的数据顺序不同,这是因为flatMap是无序的。

4.2.3 concatMap()

concatMap基本使用与flatMap使用方法相同,只不过concatMap是有序的。

4.2.4 flatMapIterable()

flatMapIterable与flatMap的使用方法相同,不同的是flatMap返回的是Observable而flatMapIterable()返回的是iterable.

4.2.5 switchMap()

switchMap()使用方式与flatMap使用方式类似,不同的是在发送连续的事件如果前一个事件未订阅完成,后一个事件就已经到达,此时前一个事件会取消,多用于网络请求之中。

4.2.6 buffer()

API

public final Observable<List<T>> buffer(int count, int skip) 

解释:
buffer是从需要发送的事件当中获取一定数量的事件,并将这些事件放到缓冲区当中一并发出。buffer有两个参数,一个是count,另一个 skip。count缓冲区元素的数量,skip就代表缓冲区满了之后,发送下一次事件序列的时候要跳过多少元素。

使用示例:

 Observable.just(1,2,3,4)
                .buffer(2,1)
                .subscribe(new Observer<List<Integer>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(List<Integer> integers) {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

4.2.7 groupBy()

API:

 public final <K> Observable<GroupedObservable<K, T>> groupBy(Function<? super T, ? extends K> keySelector, boolean delayError) 

解释:
将发送的数据进行分组,每个分组都会返回一个被观察者。在 groupBy() 方法返回的参数是分组的名字,每返回一个值,那就代表会创建一个组,以下的代码就是将0~9的数据分成3组

使用方法:

 Observable.just(5,2,3,4,1,8,9,0,7,6)
                  .groupBy(new Function<Integer, Integer>() {
                    @Override
                    public Integer apply(Integer integer) throws Exception {
                        return integer%3;
                    }
                }).subscribe(new Observer<GroupedObservable<Integer, Integer>>() {

            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(final GroupedObservable<Integer, Integer> integerIntegerGroupedObservable) {
                integerIntegerGroupedObservable.subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d("NEXTVALUE","key"+integerIntegerGroupedObservable.getKey()+"VALUE"+integer);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
4.2.8 scan()

API:

public final Observable<T> scan(BiFunction<T, T, T> accumulator) 

解释:
scan()将数据以一定的逻辑聚合起来。

代码示例:

Observable.just(1,2,3,4,5,6)
                  .scan(new BiFunction<Integer, Integer, Integer>() {
                        @Override
                        public Integer apply(Integer integer, Integer integer2) throws Exception {
                            return integer+integer2;
                        }
                    })
                  .subscribe(new Observer<Integer>() {
                      @Override
                      public void onSubscribe(Disposable d) {
                      }
                      @Override
                      public void onNext(Integer integer) {
                        Log.d("number",integer+"");
                      }
                      @Override
                      public void onError(Throwable e) {
                      }
                      @Override
                      public void onComplete() {
                      }
                  });

上述代码的逻辑输出为3,6,10,15,21

4.2.9 window()

API:

public final Observable<Observable<T>> window(long count) 

解释:
发送指定数量的事件时,就将这些事件分为一组。window 中的 count 的参数就是代表指定的数量,例如将 count 指定为2,那么每发2个数据就会将这2个数据分成一组

示例代码:

 Observable.just(1,2,3,4,5)
                .window(2)
                .subscribe(new Observer<Observable<Integer>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Observable<Integer> integerObservable) {
                        integerObservable.subscribe(new Observer<Integer>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onNext(Integer integer) {
                            Log.d("TAG",integer+"");
                            }

                            @Override
                            public void onError(Throwable e) {

                            }

                            @Override
                            public void onComplete() {

                            }
                        });
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

输出结果:分三组输出,每组两个元素
1,2;
3,4;
5;

4.3 组合操作符
4.3.1 concat()

API:

public static <T> Observable<T> concat(
        ObservableSource<? extends T> source1, ObservableSource<? extends T> source2,
        ObservableSource<? extends T> source3, ObservableSource<? extends T> source4)

方法解释:
可以将多个观察者组合在一起,然后按照之前发送顺序发送事件。需要注意的是,concat() 最多只可以发送4个事件。

使用示例:

Observable.concat(Observable.just(1,2),
                          Observable.just(3,4),
                          Observable.just(5,6),
                          Observable.just(7,8))
                  .subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG,integer.toString());
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

输出结果:1,2,3,4,5,6,7,8

4.3.2 concatArray()

与 concat() 作用一样,不过 concatArray() 可以发送多于 4 个被观察者。

4.3.3 merge()

与concat()作用一样,不过 concat() 是串行发送事件,而 merge() 并行发送事件。concat只有等到第一个被观察者发送完事件之后,第二个被观察者才会发送事件;merge()最多只可以发送4个事件。

4.3.4 mergeArray()

mergeArray() 与 merge() 的作用是一样的,只是它可以发送4个以上的被观察者。

4.3.5 concatArrayDelayError() & mergeArrayDelayError()

在 concatArray() 和 mergeArray() 两个方法当中,如果其中有一个被观察者发送了一个 Error 事件,那么就会停止发送事件,如果你想 onError() 事件延迟到所有被观察者都发送完事件后再执行的话,就可以使用 concatArrayDelayError() 和 mergeArrayDelayError()。

4.3.6 zip()

API:

public static <T, R> Observable<R> zip(Iterable<? extends ObservableSource<? extends T>> sources, Function<? super Object[], ? extends R> zipper) 

解释:
将多个被观察者合并,根据各个被观察者发送事件的顺序一个个结合起来,最终发送的事件数量会与源 Observable 中最少事件的数量一样。

示例代码:

Observable.zip(Observable.intervalRange(1, 5, 1, 1, TimeUnit.SECONDS)
    .map(new Function<Long, String>() {
        @Override
        public String apply(Long aLong) throws Exception {
            String s1 = "A" + aLong;
            Log.d(TAG, "===================A 发送的事件 " + s1);
            return s1;
        }}),
        Observable.intervalRange(1, 6, 1, 1, TimeUnit.SECONDS)
            .map(new Function<Long, String>() {
            @Override
            public String apply(Long aLong) throws Exception {
                String s2 = "B" + aLong;
                Log.d(TAG, "===================B 发送的事件 " + s2);
                return s2;
            }
        }),
        new BiFunction<String, String, String>() {
            @Override
            public String apply(String s, String s2) throws Exception {
                String res = s + s2;
                return res;
            }
        })
.subscribe(new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {
        Log.d(TAG, "===================onSubscribe ");
    }

    @Override
    public void onNext(String s) {
        Log.d(TAG, "===================onNext " + s);
    }

    @Override
    public void onError(Throwable e) {
        Log.d(TAG, "===================onError ");
    }

    @Override
    public void onComplete() {
        Log.d(TAG, "===================onComplete ");
    }
});

上面代码中有两个 Observable,第一个发送事件的数量为5个,第二个发送事件的数量为6个;最终接收到的事件数量是5,那么为什么第二个 Observable 没有发送第6个事件呢?因为在这之前第一个 Observable 已经发送了 onComplete 事件,所以第二个 Observable 不会再发送事件。

4.3.7 combineLatest() & combineLatestDelayError()

API:

public static <T1, T2, R> Observable<R> combineLatest(ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> combiner)

combineLatest() 的作用与 zip() 类似,但是 combineLatest() 发送事件的序列是与发送的时间线有关的,当 combineLatest() 中所有的 Observable 都发送了事件,只要其中有一个 Observable 发送事件,这个事件就会和其他 Observable 最近发送的事件结合起来发送.combineLatestDelayError() 就是多了延迟发送 onError() 功能,这里就不再赘述了。

4.3.8 reduce()

API:

public final Maybe<T> reduce(BiFunction<T, T, T> reducer)

与 scan() 操作符的作用也是将发送数据以一定逻辑聚合起来,这两个的区别在于 scan()每处理一次数据就会将事件发送给观察者,而 reduce() 会将所有数据聚合在一起才会发送事件给观察者。

4.3.9 collect()

API:

public final <U> Single<U> collect(Callable<? extends U> initialValueSupplier, BiConsumer<? super U, ? super T> collector)

方法解释:
将数据收集到数据结构当中。

4.3.10 startWith() & startWithArray()

在发送事件之前追加事件,startWith() 追加一个事件,startWithArray() 可以追加多个事件。追加的事件会先发出

4.3.11 count()

API:

public final Single<Long> count()

方法解释:

返回被观察者发送事件的数量。

4.4 功能操作符
4.4.1 delay()

API:

public final Observable<T> delay(long delay, TimeUnit unit)

方法解释:
延迟一段事件发送事件.

4.4.3 doOnEach()

API:

public final Observable<T> doOnEach(final Observer<? super T> observer) 

方法解释:
Observable 每发送一个事件之前都会回调doOnEach()方法,并且可以取出 onNext() 发送的值。

4.4.4 doOnNext()

API:

public final Observable<T> doOnNext(Consumer<? super T> onNext)

方法解释:
Observable 每发送 onNext() 之前都会先回调这个方法

4.4.5 doAfterNext()

API:

public final Observable<T> doAfterNext(Consumer<? super T> onAfterNext)

方法解释:
Observable 每发送 onNext() 之后都会回调这个方法

4.4.6 doOnComplete()

API:

public final Observable<T> doOnComplete(Action onComplete)

方法解释:
Observable 每发送 onComplete() 之前都会回调这个方法。

4.4.6 doOnError()

Observable 每发送 onError() 之前都会回调这个方法。

4.4.7 doOnSubscribe()

Observable 每发送 onSubscribe() 之前都会回调这个方法。

4.4.8 doOnDispose()

当调用 Disposable 的 dispose() 之后回调该方法。

4.4.9 doOnLifecycle()

在回调 onSubscribe之前回调该方法的第一个参数的回调方法,可以使用该回调方法决定是否取消订阅。doOnLifecycle() 第二个参数的回调方法的作用与 doOnDispose() 是一样的

4.4.10 doOnTerminate() & doAfterTerminate()

doOnTerminate 是在 onError 或者 onComplete 发送之前回调,而 doAfterTerminate 则是 onError 或者 onComplete 发送之后回调。

4.4.11 4.11 doFinally()

在所有事件发送完毕之后回调该方法。这里可能你会有个问题,那就是 doFinally() 和 doAfterTerminate() 到底有什么区别?区别就是在于取消订阅,如果取消订阅之后 doAfterTerminate() 就不会被回调,而 doFinally() 无论怎么样都会被回调,且都会在事件序列的最后。

4.4.12 onErrorReturn()

当接受到一个 onError() 事件之后回调,返回的值会回调 onNext() 方法,并正常结束该事件序列。

4.4.13 onErrorResumeNext()

当接收到 onError() 事件时,返回一个新的 Observable,并正常结束事件序列。

4.4.14 onExceptionResumeNext()

与 onErrorResumeNext() 作用基本一致,但是这个方法只能捕捉 Exception。

4.4.15 retry()

API:

public final Observable<T> retry(long times)

如果出现错误事件,则会重新发送所有事件序列。times 是代表重新发的次数。

4.4.16 retryUntil()

出现错误事件之后,可以通过此方法判断是否继续发送事件。

4.4.17 retryWhen()

当被观察者接收到异常或者错误事件时会回调该方法,这个方法会返回一个新的被观察者。如果返回的被观察者发送 Error 事件则之前的被观察者不会继续发送事件,如果发送正常事件则之前的被观察者会继续不断重试发送事件。

4.4.18 repeat()

API:

public final Observable<T> repeat(long times)

重复发送被观察者的事件,times 为发送次数。

4.4.19 repeatWhen()

API:

public final Observable<T> repeatWhen(final Function<? super Observable<Object>, ? extends ObservableSource<?>> handler)

这个方法可以会返回一个新的被观察者设定一定逻辑来决定是否重复发送事件。这里分三种情况,如果新的被观察者返回 onComplete 或者onError事件,则旧的被观察者不会继续发送事件。如果被观察者返回其他事件,则会重复发送事件。

4.4.20 subscribeOn()

API:

public final Observable<T> subscribeOn(Scheduler scheduler)

指定被观察者的线程,要注意的时,如果多次调用此方法,只有第一次有效。

4.4.21 observeOn()

API:

public final Observable<T> observeOn(Scheduler scheduler)

指定观察者的线程,每指定一次就会生效一次。

subscribeOn()主要改变的是订阅的线程,即call()执行的线程;
observeOn()主要改变的是发送的线程,即onNext()执行的线程。

4.5 过滤操作符
4.5.1 filter()

通过一定逻辑来过滤被观察者发送的事件,如果返回 true 则会发送事件,否则不会发送。

4.5.2 ofType()

可以过滤不符合该类型事件

4.5.3 skip()

跳过正序某些事件,count 代表跳过事件的数量。skipLast() 作用也是跳过某些事件,不过它是用来跳过正序的后面的事件。

4.5.4 distinct()

过滤事件序列中的重复事件

4.5.5 distinctUntilChanged()

过滤掉连续重复的事件

4.5.6 take()

控制观察者接收的事件的数量。takeLast() 的作用就是控制观察者只能接受事件序列的后面几件事情。

4.5.7 debounce()

如果两件事件发送的时间间隔小于设定的时间间隔则前一件事件就不会发送给观察者。throttleWithTimeout() 与此方法的作用一样,这里就不再赘述了。

4.5.8 firstElement() && lastElement()

firstElement() 取事件序列的第一个元素,lastElement() 取事件序列的最后一个元素。

4.5.9 elementAt() & elementAtOrError()

elementAt() 可以指定取出事件序列中事件,但是输入的 index 超出事件序列的总数的话就不会出现任何结果。这种情况下,你想发出异常信息的话就用 elementAtOrError() 。

4.6 条件操作符
4.6.1 all()

判断事件序列是否全部满足某个事件,如果都满足则返回 true,反之则返回 false。

4.6.2 takeWhile()

可以设置条件,当某个数据满足条件时就会发送该数据,反之则不发送。

4.6.3 skipWhile()

可以设置条件,当某个数据满足条件时不发送该数据,反之则发送。

4.6.4 takeUntil()

可以设置条件,当事件满足此条件时,下一次的事件就不会被发送了。

4.6.5 skipUntil()

当 skipUntil() 中的 Observable 发送事件了,原来的 Observable 才会发送事件给观察者。

4.6.6 sequenceEqual()

判断两个 Observable 发送的事件是否相同。

4.6.7 contains()

判断事件序列中是否含有某个元素,如果有则返回 true,如果没有则返回 false。

4.6.8 isEmpty()

判断事件序列是否为空。

4.6.9 amb()

amb() 要传入一个 Observable 集合,但是只会发送最先发送事件的 Observable 中的事件,其余 Observable 将会被丢弃。

4.6.10 defaultIfEmpty()

如果观察者只发送一个 onComplete() 事件,则可以利用这个方法发送一个值。

5、线程控制

5.1 如何进行线程控制

  我们需要在子线程中进行一系列的耗时操作,在主线程中更新UI。这就涉及到线程间的切换问题。Rxjava遵循的是线程不变的原则:即在哪个线程调用subscribe(),就在哪个线程生产、消费事件。Rxjava采用Scheduler进行切换线程。比如上游需要从服务器端请求数据,或者从数据库查询大量数据等做一下耗时任务的操作,完成后发布结果事件,下游根据接受的事件来显示界面,这时就需要控制上下游的线程了。subscribeOn()用于指定上游的线程也就是subscrobe()所发生的的线程,即Observable.OnSubscribe被激活时所处的线程,或者叫做事件产生的线程,observerOn()用于指定下游的线程,指定的是所运行的线程,或者叫做事件消费的线程。

API:

public final Observable<T> subscribeOn(Scheduler scheduler);

public final Observable<T> observeOn(Scheduler scheduler) ;

这两个方法都接受调度器Scheduler参数;

调用器作用
Schedulers.newThread()总是启用新线程,并在新线程执行操作
Schedulers.io()(读写文件、读写数 据库、网络信息交互等)
行为模式和 newThread() 差不多,区别在于
io()的内部实现是是用一个无数量上限的线程
池,可以重用空闲的线程,因此多数情况下 io()
比newThread()更有效率。不要把计算工作放
在 io() 中,可以避免创建不必要的线程。
Schedulers.computation()计算所使用的 Scheduler。这个计算指的是
CPU 密集型计算,即不会被 I/O 等操作限制性
能的操作,例如图形的计算。这个 Scheduler
使用的固定的线程池,大小为CPU核数。不要
把 I/O 操作放在computation()中,否则I/O操作的
等待时间会浪费 CPU。
AndroidSchedulers.mainThread()它指定的操作将在 Android 主线程运行。
5.2 subscribeOn()

通过subscribeOn()和observeOn()可以指定上下游所工作的线程,如果我们只指定下游工作的线程,也即只调用observerOn(),而不指定上游工作的线程,也即不调用suscribeOn(),那么上游线程即为当前所工作的线程;如果我们只指定上游线程,不指定下游线程,那么上下游线程保持一致。无论上下游指定什么线程,onSubscribe()始终是在订阅操作所在的线程执行,如果订阅线程在主线程,那么它就在主线程。如果订阅线程在子线程中,我们想在onSubscribe()中刷新UI怎么办呢?,我们可以通过上面所说的操作符中的doOnSubscribe(),它是在订阅之前调用的,通过使用subscribeOn()来指定doOnSubscribe()在哪个线程中执行:doOnSubscribe()之前的subscribeOn()不会影响它的线程,doOnSubscribe()之后的subscribeOn(),且是最近的才会影响它。subscribeOn作用范围是从它开始往上,如果多次调用subscribeOn,上游的线程为从下往上,离它最近的那个subscribeOn指定的线程。因此在doOnSubscribe()之后,使用subscribeOn()就可以指定其运行在哪中线程。另外除了 doOnSubscribe 以外,还有对应的 doOnNext,doOnComplete,doOnError,这三个方法的线程始终与发布事件的线程相同。

以下示例代码很好的阐述了suscribeOn的控制关系:


Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
        Log.d(TAG,"Observable_subscribe"+Thread.currentThread().getName());
        //打印的结果:Thread—2这个线程是被观察者发布事件所在的线程;
        emitter.onNext(0);
        emitter.onNext(1);
        emitter.onComplete();
    }
}) .subscribeOn(Schedulers.newThread()) //Thread-2,它控制发布事件所在的线程
   .doOnSubscribe(new Consumer<Disposable>() {
            @Override
            public void accept(Disposable disposable) throws Exception {
                Log.d(TAG,"doOnSubscribe_accept"+Thread.currentThread().getName());
                //打印结果:Thread-1
            }

        })
    .doOnNext(new Consumer<Integer>() {
        @Override
        public void accept(Integer integer) throws Exception {
            Log.d(TAG,"doOnNext_accept"+Thread.currentThread().getName());
            //打印结果:Thread-2,它始终与发布事件所在的线程一致,除此之外doOnErro\doOnComplete一样
        }
    })
    .subscribeOn(Schedulers.newThread())//Thread-1,它控制doOnSubscribe所在的线程
    .subscribeOn(AndroidSchedulers.mainThread())//Thread-4 //这个指定的线程,没有任何意义
    .observeOn(Schedulers.newThread())//Thread-3,它控制着观察者所在的线程
    .subscribe(new Observer<Integer>() {
       @Override
       public void onSubscribe(Disposable d) {
           //执行订阅操作所在的线程,不受subscribeOn和observeOn的影响
           Log.d(TAG,"Observer_onSubscribe"+Thread.currentThread().getName());
       }

       @Override
       public void onNext(Integer integer) {
           //打印结果:Thread-3
           Log.d(TAG,"Observer_onNext"+Thread.currentThread().getName());
       }

       @Override
       public void onError(Throwable e) {
           //如有结果也是:Thread-3
           Log.d(TAG,"Observer_onError"+Thread.currentThread().getName());
       }

       @Override
       public void onComplete() {
           //打印结果:Thread-3
           Log.d(TAG,"Observer_onComplete"+Thread.currentThread().getName());
       }
   }) ;
5.3 observeOn()

onserverOn的执行顺序和subscribeOn()正好相反,observeOn作用范围是从它开始往下,如果多次调用observeOn,下游的线程为从上往下,离它最近的那个 observeOn 指定的线程。

示例代码:

   Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            emitter.onNext(0);
            emitter.onNext(1);
            emitter.onComplete();
            Log.d(TAG,"Observable_subscribe  "+Thread.currentThread().getName());
            //打印结果:Thread-1
        }
    }).subscribeOn(Schedulers.newThread())//Thread-1//控制发布事件所在的线程
      .observeOn(Schedulers.newThread())//Thread-2//控制map所在的线程
      .map(new Function<Integer, String>() {
          @Override
          public String apply(Integer integer) throws Exception {
              Log.d(TAG,"map_apply  "+Thread.currentThread().getName());
              //打印结果:Thread-2
              return integer.toString();
          }
    }).observeOn(Schedulers.newThread())//没有意义,就近原则
      .observeOn(AndroidSchedulers.mainThread())//控制下游消费事件所在的线程
      .subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {
                Log.d(TAG,"Observer_onSubscribe  "+Thread.currentThread().getName());
                    //执行订阅操作所在的线程,不受subscribeOn和observeOn的影响
                }

                @Override
                public void onNext(String s) {
                    //打印结果为main
                    Log.d(TAG,"Observer_onNext  "+Thread.currentThread().getName());
                }

                @Override
                public void onError(Throwable e) {
                    //打印结果为main
                    Log.d(TAG,"Observer_onError  "+Thread.currentThread().getName());
                }

                @Override
                public void onComplete() {
                    //打印结果为main
                    Log.d(TAG,"Observer_onComplete  "+Thread.currentThread().getName());
                }
            });

通过以上描述我们可以知道使用subscribeOn()和observeOn()进行线程的控制。

6、背压策略

6.1 什么是背压?

我们知道Rxjava是基于观察者模式而设计的,那么当被观察者产生的数据,或者我们说当上游产生的数据大于下游处理数据的速度,如果这个时候我们不做处理,会导致事件的堆积,抛出MissingBackpressureException;这时我们就需要进行控流操作。
通常的控流操作有以下几种:

  1. 背压(Backpressure);
  2. 节流(Throttling);
  3. 打包处理;
  4. 调用栈阻塞;

节流说白了就是做丢弃那些处理不了的数据包,常见的策略可以参考前面我们所说的过滤操作符的操作。打包处理就是将上游来的小包裹打成大包裹,分发到下游,比如我们前面说的操作符中的buffer和window;调用阻塞就是阻塞上游发送的数据,不过已经在2.0废弃;我们再来说一下背压,背压就是一种在异步处理过程中,一种控流策略了.背压策略其实是一种响应式拉取策略,在Rxjava的设计中被观察者是主动的推送数据给观察者,观察者是被动的接收数据。而响应式拉取则是,观察者根据自身需要,主动从被观察者那里拉取数据。

6.2 如何使用背压策略

在Rxjava1.x中有些Observable是支持背压的,而有些不支持,可以通过一些操作符操作符转换成支持背压操作的,在Rxjava2中,Observable不在支持背压,而是改用Flowable支持非阻塞式的背压,Flowable默认队列大小为128。Flowable的有三种背压策略:

  • BackpressureStrategy.BUFFER
  • BackpressureStrategy.DROP
  • BackpressureStrategy.LATEST

第一种背压策略就是将上游收到的全部数据缓存下来,等下游来请求再发给下游。第二种和第三种都是丢弃数据,但是有细微的差别,下游通过request()请求产生配额给上游,上游接到多少配额,就给下游发送多少数据。当令牌消耗数量为0的时候,上游开始丢弃数据,第二种丢弃的方式是直接丢弃,而第三种是缓存最新的一条数据,当上游接到新配额的时候就会把缓存的数据发送给下游。

示例:

 Flowable.just(1,2,3, BackpressureStrategy.BUFFER)
                .observeOn(Schedulers.newThread())
                .subscribe(new Subscriber<Serializable>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        s.request(1);
                    }

                    @Override
                    public void onNext(Serializable serializable) {
                    }

                    @Override
                    public void onError(Throwable t) {
                    }

                    @Override
                    public void onComplete() {

                    }
                });

那么如何选择使用Observable和Flowable呢?当上游在一段时间内发送的数据量不大(以1000为界限)的时候优先使用Observable;获取的数据时同步的,使用Observable的性能要高于Flowable.但是当我们读取本地磁盘某个文件,或查询数据库数量很大的情况下,有阻塞线程的可能,我们使用Flowable,下游可以根据某种条件自己主动读取数据。

7、Rxjava2中的观察者模式

Observable/Observer

Flowable/Subscriber

除了这两种观察者模式以外还有

Single/SingleObserver:订阅后只能接收到一次

Completable/CompletableObserver:只能接收到完成(onComplete)和错误(onError)回调。

Maybe/MaybeObserver:只能接收到一次true或false的数据

三、总结

这篇文章算是对Rxjava2的使用的简单梳理,如果有什么错误的地方欢迎指正。

四、参考文章

扔物线:http://gank.io/post/560e15be2dca930e00da1083

任玉刚:https://juejin.im/post/5b17560e6fb9a01e2862246f#heading-68

一叶飘舟:https://blog.csdn.net/jdsjlzx/article/details/51534504

欢迎关注我的个人公众号
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值