RxJava/RxAndroid 使用入门

RxJava 用途

异步操作、数据变换

RxJava 集成方式

    implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

RxJava 概念

RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。
他们之间的关系可以用下图表示:
关系图

RxJava 基本实现

根据上面说的,实现起来大概可以分为三步:
1.创建 Observeable
2.创建一个 Observer
3.订阅

创建 Observer

Observer<String> observer = new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {
        mDisposable = d;
    }

    @Override
    public void onNext(String value) {
        Log.d(TAG, value);
    }

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

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

Observer 中提供了四个方法,onNext(String value)、onError(Throwable e)、onComplete()方法分别对应 onNext、onError、onComplete 事件。
onSubscribe(Disposable d) 方法在订阅后会最先被调用,其中包含一个 Disposable 对象,Disposable 用于取消订阅,比如我们可以在 Activity 的 onDestroy 中调用 mDisposable.dispose();

此外还有一种方式创建 Observer

Subscriber<String> subscriber = new Subscriber<String>() {

    @Override
    public void onSubscribe(Subscription s) {
        mSubscription = s;
    }

    @Override
    public void onNext(String value) {
        Log.d(TAG, value);
    }

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

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

看起来都差不多的其实,区别就在于 onSubscribe(Subscription s) 方法的参数由 Disposable 变成了 Subscription ,Subscription 中包含两个方法:
1.cancel() :等同于 mDisposable.dispose() 方法;
2.request(long n) :背压,用于告诉上游线程要发送多少数据,这个用的比较少,就不多做解释了,想深入了解的请看:https://juejin.im/post/582b2c818ac24700618ff8f5

创建 Observable

Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> e) throws Exception {
        subscriber.onNext("hello");
        subscriber.onNext("world");
        subscriber.onComplete();
    }
});

上面通过 create() 方法创建了一个 Observable 并发送了三个事件。

发送事件规则:
onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。

onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。

除了普通的 create() 方式创建之外还提供了其他几种简化方式:

1. just(T...): 将传入的参数依次发送出来。

Observable observable = Observable.just("Hello", "world");
// 将会依次调用:
// onNext("Hello");
// onNext("world");
// onCompleted();

2. from(T[]) / from(Iterable < ? extends T>): 将传入的数组或 Iterable 拆分成具体对象后,依次发送出来。

String[] words = {"Hello", "world"};
Observable observable = Observable.from(words);
// 将会依次调用:
// onNext("Hello");
// onNext("world");
// onCompleted();

上面两种创建方式本质上都是跟 create() 一样。

订阅(Subscribe)

observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);

除了上面这两种方式之外还支持不完整的调用,RxJava 会自动根据定义创建出 Subscriber:

Consumer<String> onNext = new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        //泛型为String,所以用来充当接收 onNext 事件的角色
        Log.d(TAG, s);
    }
};

Consumer<Throwable> onError = new Consumer<Throwable>() {
    @Override
    public void accept(Throwable throwable) throws Exception {
        //泛型为 Throwable ,用来充当接收 onError 事件的角色
        Log.d(TAG, throwable.toString());
    }
};

Action onComplete = new Action() {
    @Override
    public void run() throws Exception {
        //没有参数,用来充当接收 onComplete 事件的角色
        Log.d(TAG, "onComplete");
    }
};

//只响应 onNext 事件
observable.subscribe(onNext);
//响应 onNext 及 onError 事件
observable.subscribe(onNext, onError);
//响应 onNext 、 onError 及 onComplete 事件
observable.subscribe(onNext, onError, onComplete);

Consumer 泛型类型可以用来区分 onNext 或 onError,Action 不包含参数,所以用来接收 onComplete 事件。

线程控制——Scheduler

在 RxJava 中使用 Scheduler(调度器)来控制线程,Scheduler 提供了如下几种线程:

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

通过 subscribeOn 方法及 observeOn 方法控制线程:

  • subscribeOn:Observable 运行线程;
  • observeOn:Observer 运行线程。

如下:

Observable
        .just("hello", "world")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(s -> Log.e(TAG, s));

数据变换

RXJava 的数据变换跟 Java8 提供的数据变换基本类似,大家可以看我的另一篇博客:https://blog.csdn.net/u013872857/article/details/79439444
但是 Java8 的数据变换对 Android 有兼容性问题,所以大多数时候还是使用 RxJava。
这里大概介绍一下,RxJava 中提供了大量的方法及接口用于实现数据变换功能,举个栗子:
现在要将一个存储文件路径的 String 列表转换成 File 列表,并判断非空,用RxJava 我们可以这么写:

Observable
        .just("mnt/sdcard/1.txt", "mnt/sdcard/2.txt", "mnt/sdcard/3.txt")
        .map(path -> new File(path))
        .filter(File::exists)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(s -> Log.e(TAG, s.getPath()));

上面的 map 方法用于将一种数据类型的流映射成另外一种数据类型的流,filter 顾名思义,用于实现筛选功能,看起来很简单也很常用。


本文很大程度上参考了扔物线这篇博客,特此感谢。

猜你喜欢

转载自blog.csdn.net/u013872857/article/details/80344997