我学 rxjava 2(1)- 简单上手

本系列目录:我学 rxjava - 目录
Android 知识梳理目录:知识梳理

啥叫 rxjava

官方文档解释:

RxJava:a library for composing asynchronous and event-based programs using observable sequences for the Java VM
// 翻译:RxJava 是一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库

通俗解释:

//  Android中的 AsyncTask 、Handler

rxjava 完成的工作就是异步,期中采用了响应式编程的理念,现在响应式编程不明白没关系,不影响你用 rxjava 完成开发,响应式编程现在桃李满天下呢,用不了多久就明白了并深有体会了,推荐学完 rxjava 再去看 Google 的 AAC 响应式组件,你就对响应式编程非常明白了,这里不要脸的推荐自己的文章:Android Architecture Components 开发架构

添加依赖

dependencies {

// Android 支持 Rxjava
// 此处一定要注意使用RxJava2的版本
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

// Android 支持 Retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'

// 衔接 Retrofit & RxJava
// 此处一定要注意使用RxJava2的版本
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

// 支持Gson解析
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

}

依赖可能的错误如下:


944365-b3574a3808108707.png

请在相关 module 中的 build.gradle 中

android {
    ...
    packagingOptions {
        exclude 'META-INF/rxjava.properties'
    }
}

rxjava 采用的是观察者设计模式, 必然就是在 Observable 被观察者 身上注册 Observer 观察者了,我们定义 Observable 如何产生,产生什么数据,然后 Observer 如何消费数据,整个套路基本就是这样,当然里面有很设置和变化啦

rxjava 里面有很多没接触过的,不好记的关键字,记住这些关键字才能玩的转 rxjava

关键字:

  • 被观察者(Observable) 产生事件 顾客
  • 观察者(Observer) 接收事件,并给出响应动作 厨房
  • 订阅(Subscribe) 连接 被观察者 & 观察者 服务员
  • 事件(Event) 被观察者 & 观察者 沟通的载体 菜式

创建 Observable 被观察者对象

rxjava 中的 Observable 被观察者一般都是要传入数据,或是能产生数据的对象才能创建出来的,所以我也喜欢管 Observable 叫数据源,要是没有 Observable 这个数据源提供数据,后面怎么消费数据呢

  // 传入可以产生数据的对象方式创建 Observable  对象
  Observable object = Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                // emitter 是用来提供数据的,我们也叫发射 
                emitter.onNext("数据");
            }
        });
    
        // 直接用数据创建 Observable  对象,数据可以是单个也可以是动态数组,集合
        Observable just = Observable.just("aaa");
        Observable list = Observable.just("", "", "");

创建 Observer 观察者并定义处理事件的行为

 Observer observer = new Observer() {
            @Override
            public void onSubscribe(Disposable d) {
                // 观察者在接受到数据之前,先执行该方法
            }

            @Override
            public void onNext(String value) {
                // 观察者此时接受到数据,可以处理数据了
            }

            @Override
            public void onError(Throwable e) {
                // 观察者接受到错误信号,进行相关处理
            }

            @Override
            public void onComplete() {
                //  观察者此时已经处理完数据了,执行该方法最最后的收尾工作。
            }
        };

Observer 观察者里面有4个方法,上面的方法里的文字基本描述清楚了,然后我想说下 Error 错误信号可以用前面 数据源里面的 emitter.onError(xxx) 自己发射出来,也会接受到这个过程中系统抛出的异常。onComplete 是不管什么情况最后都会走的。

现在 Observable 有了 ,Observer 也有了,他俩一注册就成了。

observable.subscribe(observer);

我们要注意数据产生的点,Observable 只是提供数据,不是我们创建一个 Observable 对象就去获取数据,发射数据了,而是再 Observer 注册到 Observable 身上那一瞬间,Observable 才还是提供数据,是远程数据的开始从远程获取数据,是现成数据的开始发射数据给 Observer 消费数据。

线程变换

观察者设计模式只是对 数据源 和 数据消费者 的一种组织形式,还不是 rxjava 最核心的内容,大家可以不要忘了 rxjava 可是替代 asynctask ,handle 这样的异步线程啊,方便的多线程操作和切换才是 rxjava 最大的核心内容

rxjava 提供一下几个线程池:

  • Schedulers.immediate()
    当前线程
  • AndroidSchedulers.mainThread()
    Android主线程
  • Schedulers.newThread()
    常规新线程
  • Schedulers.io()
    io操作线程,可以进行网络请求、读写文件等io密集型操作
  • Schedulers.computation()
    CPU计算操作线程,线程数据同 CPU 核心数

相关的线程控制 API 如下,这里是简单的写的

 observable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
  • subscribeOn 是描述 observable 中产生数据的方法执行在哪个线程
  • observeOn 是描述 observer 消费数据的方法执行在哪个线程
  • 这里 数据源是从网络获取数据,UI 线程消费数据

关于 Observer 的变形

我们按照上面的 方式创建一个 Observer 来,需要实现4个方法才行,丰富多看着乱,页影响 rxjava 的链式调用阅读效果,官方提供了如下的 Observer 创建方法

   // 表示观察者不对被观察者发送的事件作出任何响应(但被观察者还是可以继续发送事件)
    public final Disposable subscribe()
 
    // 表示观察者只对被观察者发送的Next事件作出响应
    public final Disposable subscribe(Consumer onNext) {}
  
    // 表示观察者只对被观察者发送的Next事件 & Error事件作出响应
    public final Disposable subscribe(Consumer onNext, Consumer onError) {} 
    
    // 表示观察者只对被观察者发送的Next事件、Error事件 & Complete事件作出响应
    public final Disposable subscribe(Consumer onNext, Consumer onError, Action onComplete) {}
    
    // 表示观察者只对被观察者发送的Next事件、Error事件 、Complete事件 & onSubscribe事件作出响应
    public final Disposable subscribe(Consumer onNext, Consumer onError, Action onComplete, Consumer onSubscribe) {}
  
    // 表示观察者对被观察者发送的任何事件都作出响应
    public final void subscribe(Observer observer) {}

Consumer 是一个方法包装接口,Observer 中的4个方法对应 4个 Consumer 方法包装接口,subscribe 注册方法中可以接受 1 - 4个 Consumer 可变参数,根据下面图 4个方法的顺序,传入一个是代替 onNext 方法,传入2个是代替 onNext、onError 方法

Consumer_方法包装接口_替换方法顺序如下

关于可能的内存泄露的处理

这些注册的 Observer 我们都是在 activity 中进行的,按照:匿名内部类持有外不累的引用,这个注册的匿名 Observer 对象其实是把我们的 activity 带出 activity 的生命周期外去了,Observable 持有这些注册的 Observer 对象引用,那么间接的也持有了 activity 的引用,在 activity 关闭时这就是个麻烦事了,原因不就是老生常谈的内存泄露了嘛...

针对这个情况,其实我们是游处理办法的,那就是 Disposable 管道这个对象,Disposable 是实际管理 Observable和 Observer 关系的操作类,我们用 Disposable 就可以接触 Observable 和 Observer 的注册的关系。

Disposable 有2种获取方式,一个是注册时我们使用 Consumer 代替 Observer ,然后我们就可以获取这个 Disposable 对象,调用 disposable.dispose() 就可以解绑

        Disposable disposable = Observable
                .just("22")
                .subscribe(
                        new Consumer() {
                            @Override
                            public void accept(String s) throws Exception {

                            }
                        }
                        , new Consumer() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {

                            }
                        });

        disposable.dispose();

或者是 Observer 对象中的 onSubscribe(Disposable d) 方法中,我们可以获取到 Disposable 对象

若是我们有多个 disposable 对象,我们可以使用官方提供管理类

        CompositeDisposable compositeDisposable = new CompositeDisposable();
        // 添加 disposable 管道对象用于统一管理
        compositeDisposable.add( disposable );
        // 统一解绑
        compositeDisposable.dispose();

一个完成的流程示例

rxjava 2 中添加了不少 doOnXXX 方法,打都是在指定的 OnXXX 方法之前执行的。

需要注意的是 2个 observeOn 方法中间夹一个 doOnNext 方法,这是说前一个 observeOn 指定 这个 doOnNext 方法的执行线程,后一个 observeOn 方法执行最终执行 Observer 执行线程,其实这个就是 rxjava 的变换操作符的基础

  Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(@NonNull ObservableEmitter e) throws Exception {
                Log.d(TAG, " subscribe.../thread: " + Thread.currentThread().getName() + "处理数据,产生事件");
                e.onNext("HH");
            }
        })
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        Log.d(TAG, " doOnSubscribe.../thread: " + Thread.currentThread().getName() + "预热方法(doOnSubscribe函数),最先执行");
                    }
                })
                .observeOn(Schedulers.computation())
                .doOnNext(new Consumer() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d(TAG, " doOnNext.../thread: " + Thread.currentThread().getName() + "数据处理后,先执行我,再发射数据");
                    }
                })
                .observeOn(Schedulers.newThread())
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        Log.d(TAG, " onSubscribe.../thread: " + Thread.currentThread().getName() + "预热方法(观察者),最先执行");
                    }

                    @Override
                    public void onNext(@NonNull String s) {
                        Log.d(TAG, " onNext.../thread: " + Thread.currentThread().getName() + "接受数据,消费事件");
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

一个完整的简单实用就是这样了,这里各种生命周期函数写的比较全了,直接看结果:


Snip20171010_25.png

按照执行顺序:

  • doOnSubscribe() 方法最先执行,所在线程是UI 线程,调用测试方法的线程
  • subscribe / onSubscribe() ,之后是观察者新添加方法,所在线程也是UI 线程,和doOnSubscribe()一样,这俩用一个就行
  • create / subscribe() ,接下来是处理数据,发射事件的线程
  • doOnNext(),这个是在数据发射之前执行的,我们可以指定一个线程,这里指定的计算线程,要是不注定,则使用发射事件的线程
  • Observer / onNext(),最后就是我们接受事件啦。

注意上面各种方法所在线程,不要弄混了

你可能感兴趣的:(我学 rxjava 2(1)- 简单上手)