Rxjava的介绍之使用篇

时间:2022-09-29 05:28:28

一、Rxjava的简介

    RxJava的可以非常简便的让开发者在复杂逻辑中完成异步调用。并且在逻辑复杂加深,和需求变更之后依然可以很好的保持简洁性。RxJava的特性可以归纳为两点,异步和简洁。

二、RxJava中的观察者模式

    RxJava采用了观察者模式来实现内部的逻辑,观察者模式包括以下几个角色和订阅: 
  被观察者:Observable 
  观察者:Observer、Subscriber 
  观察的事件订阅:subscribe

三、RxJava的使用

  3.1 RxJava的基本用法

  RxJava在使用可以分为三步:1.创建被观察者;2.创建观察者;3.通过subscribe函数完成观察者对被观察者的订阅,下面是RxJava的一个基本调用示例代码。

     Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                //执行完毕,触发回调,通知观察者
                e.onNext("回调的信息");
            }
        });
    
    Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            //观察者接收到通知,进行相关操作
            public void onNext(String message) {
                System.out.println(message);//"回调的信息"
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        };

   observable.subscribe(observer);
  3.2 RxJava创建Observable的方法

    create方法

    create方法中传入了一个ObservableOnSubscribe对象,该对象是一个泛型类,类型由客户来定,onNext回调的参数值是类型T的一个实例对象。

    Observable<T> observable = Observable.create(new ObservableOnSubscribe<T>() {
                @Override
                public void subscribe(ObservableEmitter<T> e) throws Exception {
                    e.onNext(new T());
                }
            });

    Just方法

    Just方法用于将快速创建事件队列回调到观察者中,Just代码定义如下

     public static <T> Observable<T> just(T ...) { //在源码中T类型的参数最多可以定义10
           ...
        }

    Just代码使用范例

    Observable observable = Observable.just("Hello","Hi","Aloha");

    // 观察者中将会依次调用:
    
    // onNext("Hello");
    
    // onNext("Hi");
    
    // onNext("Aloha");
    
    // onCompleted();

    fromIterable方法

    fromIterable方法的使用范例如下:

    List<String> list = new ArrayList<String>();
    for(int i =0;i<10;i++){
        list.add("Hello"+i);
    }
    Observable<String> observable = Observable.fromIterable((Iterable<String>) list);

    fromIterable方法会遍历参数列表中的所有元素,将他们一一回调到观察者。

    defer方法

    根据源码中的翻译,defer()当观察者订阅时,才创建Observable,并且针对每个观察者创建都是&一个新的Observable。针对defer()的进一步解释可以参见如下代码:

    //一个数据类代码
    public class SomeType {  
    private String value;
    
    public void setValue(String value) {
      this.value = value;
    }
    
    public Observable<String> valueObservable() {
      return Observable.just(value);
    }
    }
    
    //调用上面的数据类代码
    SomeType instance = new SomeType();  
    Observable<String> value = instance.valueObservable(); //已经完成了value的初始化 
    instance.setValue("Some Value");  
    value.subscribe(System.out::println);

    在上面的调用段代码中期望能够打印出“Some Value”,但是结果是打印NULL,因为在调用Observable.just(value);创建一个Observable对象时,已经用没有初始化的value值进行构造了。为了能够保证结果最终打印出“Some Value”,采用defer()重新编写数据类代码如下:

    public Observable<String> valueObservable() {
      return Observable.defer(new Func0<Observable<String>>() {
        @Override public Observable<String> call() {
          return Observable.just(value);
        }
      });
    }

    interval( )方法

    interval方法可创建一个间隔一段时间就发送数据的Observable,比如如下代码就是每隔2秒就会去调用一次观察的这onNext函数。

    Observable<String> observable = Observable.interval(2, TimeUnit.SECONDS);

    需要注意的一点就是,在使用interval()创建Observable时,使用的是默认的Schedulers.computation(),而Observable回调是在另一个线程,如果在确认观察者和被观察者的订阅关系之后就退出了,被观察者定义的事件将不会被观察者执行到。如果需要观察者执行被观察者的事件,建议在订阅之后加一个长长的sleep。

    timer()方法

    timer()方法会创建一个Observable,它在一个给定的延迟后发射一个特殊的值,并不会周期性的执行。如下代码是在2s的延时后,让观察者调用onNext()。

    Observable<Integer> observable = Observable.timer(2, TimeUnit.SECONDS);

    Observabler创建的方法还有很多,比如fromArray,merge和repeat等。

    3.3 RxJava中其它关键字和操作符

    Action和FunctionX

    Action和Function0的源码定义如下:

    public interface Action {
        /** * Runs the action and optionally throws a checked exception. * @throws Exception if the implementation wishes to throw a checked exception */
        void run() throws Exception;
    }
    
    public interface Function<T, R> {
    /** * Apply some calculation to the input value and return some other value. * @param t the input value * @return the output value * @throws Exception on error */
    R apply(@NonNull T t) throws Exception;
}

    Action是RxJava中定义的一个接口,没有返回值,通常被用来定义一个实现的对象作为参数传入subscribe()来实现观察者端的回调,如示下代码:

    
    Observable.just("Hello", "World").subscribe(new Action() {
                    @Override
                    public void run() throws Exception {
                        throw new IllegalArgumentException();
                    }
                }));

    Function一般是用来配合操作符map完成对参数对象的转换,如下示例代码,即可完成了从请求String类型的对象到Bitmap对象的转换。

    Observable.just("images/logo.png") // 输入类型 String
        .map(new Function<String, Bitmap>() {
            @Override
            public Bitmap apply(String filePath) { // 参数类型 String
                return getBitmapFromPath(filePath); // 返回类型 Bitmap
            }
        })
        .subscribe(new DefaultSubscriber<Bitmap>() {
            @Override
            public void onNext(Bitmap bitmap) { // 参数类型 Bitmap
                showBitmap(bitmap);
            }
        });

    map和flatmap

    如此前的示例代码,map主要的作用是将事件序列中的对象在经过一段逻辑调用之后转换成不同的对象。flatmap和map类似都是将传入的参数转换和返回另一个对象输出,但是在RxJava2.x版本中,map方法和flatmap方法最终调用了RxJavaPlugins.onAssembly。

    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper,
            boolean delayErrors, int maxConcurrency, int bufferSize) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        if (this instanceof ScalarCallable) {
            @SuppressWarnings("unchecked")
            T v = ((ScalarCallable<T>)this).call();
            if (v == null) {
                return empty();
            }
            return ObservableScalarXMap.scalarXMap(v, mapper);
        }
        return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, maxConcurrency, bufferSize));
    }

    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }

    但是与map方法不同的是flatMap()中转换返回的是个Observable对象,并且这个Observable对象并不是被直接发送到了Subscriber的回调方法中。参见此前的范例,map方法中返回的是是一个BitMap对象。flatmap()的原理如下:1. 使用传入的事件对象创建一个Observable对象;2. 并不发送这个Observable, 而是将它激活,于是它开始发送事件;3. 每一个创建出来的Observable发送的事件,都被汇入同一个Observable,而这个Observable负责将这些事件统一交给Subscriber的回调方法。

    flatmap的范例代码参见如下代码:

    //获取每个学生所修的所有课程
    Student[] students = ...;
    Subscriber<Course> subscriber = new Subscriber<Course>() {
        @Override public void onNext(Course course) {
            Log.d(tag, course.getName());
        }
        ...
    };
    Observable.from(students)
        .flatMap(new Func1<Student, Observable<Course>>() {
            @Override public Observable<Course> call(Student student) {
                return Observable.from(student.getCourses());
            }
        })
        .subscribe(subscriber);

    filter和take操作符

    filter主要用来对事件的过滤,筛选,添加对事件是否需要发送的判断,可参见如下示例代码

    Observable.just(1, 2, 3, 4, 5, 6)//创建了一个有6个数字的被观察者
        .filter(new Predicate<Integer>() {//添加筛选器
            @Override
            public boolean test(Integer integer) throws Exception {//对每个事件进行筛选,返回true的保留
                    return integer % 2 == 0;
                }
            })
        .subscribe(System.out::println);//运行结果输出2 4 6

    take可以限定被观察者发送前n个items或者是在设定内能够发送的items。参见如下示例代码:

    Observable.just(1, 2, 3, 4, 5)
            // 运行在后台线程
            .subscribeOn(Schedulers.io())
            // 运行在主线程
            .observeOn(AndroidSchedulers.mainThread())
            //注意take操作符->只发送前三个事件
            .take(3)
            .subscribe(System.out::println);//运行结果输出1 2 3 

    3.4 RxJava中的线程调度器Scheduler

    Scheduler的API

API列表 API介绍
Schedulers.immediate() 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
Schedulers.newThread() 总是启用新线程,并在新线程执行操作。
Schedulers.io() I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。
Schedulers.computation() 计算所使用的 Scheduler
AndroidSchedulers.mainThread() 它指定的操作将在 Android 主线程运行。

    Scheduler指定线程

    observerOn(Schedulers),指定观察者Observer在哪个线程执行

    subscribeOn(Scheduler),指定被观察者Observable在哪个线程执行

    通过observerOn(Schedulers)和subscriberOn(Scheduler)可以实现线程间的随意切换,参见如下代码demo:

Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定
    .subscribeOn(Schedulers.io())
    .observeOn(Schedulers.newThread())
    .map(mapOperator) // 新线程,由 observeOn() 指定
    .observeOn(Schedulers.io())
    .map(mapOperator2) // IO 线程,由 observeOn() 指定
    .observeOn(AndroidSchedulers.mainThread) 
    .subscribe(subscriber);  // Android 主线程,由 observeOn() 指定

     四、总结

    本文主要总结归纳了rxjava中常用的方法,比如Observable不同的创建方式,被观察者和观察者转针对不同观察对象的转换操作、过滤以及限定输出等,最后还介绍了将观察者和被观察者放在不同的线程中进行执行,执行过程中线程的切换等。该文主要是为了熟悉阅读源码所做的铺垫,后续会对rxJava的源码进行分析。

该博文参考了如下链接信息:

https://www.jianshu.com/p/d149043d103a

https://www.jianshu.com/p/1c44c7a49f75