RxJava2.0(一)快速使用

331 阅读7分钟

前言

现在很多地方都在讲响应式编程的概念,RxJava被炒得很热,感觉在项目里面不用或者不会RxJava都不好意思说你懂Android开发。但是很多人每天都在使用RxJava,却很少有懂他到底是什么或者具体的一些使用方式和方法。他们完全是照搬硬套对其中的一些细节却知之甚少。下面,我来根据我自己在平时使用中的理解,具体讲一讲RxJava的一些知识点。

RxJava是什么?

很多人在被问到这个问题的时候可以说是一脸懵逼的状态,因为压根就没想过这个问题。或者长篇大论一通说,最后还是说的云里雾里。

其实RxJava在我看来就是两个词概括。观察者模式异步操作

什么是观察者模式?

举个例子,警察抓小偷。法律讲究后发制人。当一个小偷还没有偷东西的时候,警察是拿他没办法的,但是警察会死死盯着他,一旦他偷了东西便立马抓获他。观察者模式也是如此。

RxJava中,也是采用观察者模式来设计的。里面有三个身份,观察者(Observer)、被观察者(Observable)、订阅(Subscribe)。其中观察者代表警察,被观察者代表小偷,两者通过订阅联系在一起。指定了这个警察每天24小时专门观察这个小偷的一举一动,如果开始偷东西,便将其抓获。

例子:

我们在使用RxJava的时候必须先添加依赖:


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

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

//被观察者
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("aa");
                e.onNext("bb");
                e.onNext("cc");
                e.onNext("dd");
                e.onComplete();
            }
        });

        //观察者
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                //TODO 初始化数据
            }

            @Override
            public void onNext(String value) {
                //TODO 接收被观察者发送的数据
                Log.i("result:",value);
            }

            @Override
            public void onError(Throwable e) {
                //TODO 错误

            }

            @Override
            public void onComplete() {
                //TODO 完成之后回调
            }
        };

        //订阅
        observable.subscribe(observer);

结果:

        demo I/result:: aa
        demo I/result:: bb
        demo I/result:: cc
        demo I/result:: dd

可以看到,我们在被观察者Observable中的subscribe中将事件通过onNext()方法发送出来,然后通过在事件发送完毕之后通过onComplete()告知事件已经全部发送完毕。而在观察者Observer中拥有四个方法

  • onSubscribe(Disposable d):这个方法在被观察者Observable还没发送onNext()的时候调用,一般可以用来初始化一些控件,或者显示dialog加载等操作。并且参数disposable有一个功能,就是可以随时停止观察者的接收功能。 d.dispose();

  • onNext():在这个方法里面进行被观察者数据发送的接收操作

  • onComplete():当上游被观察者调用onComplete()方法时,回调这个接口。主要在这里面进行一些注销操作。比如一开始加载loading的dismiss操作。

  • onError(Throwable e):当有错误出现的时候回调这个方法。

当写完了观察者和被观察者的逻辑之后,我们通过subscribe()方法将两者进行订阅操作。这里需要注意一下,RxJava中是被观察者订阅观察者,而不是观察者订阅被观察者,这个需要特别注意。

引以为傲的链式结构:

        //链式结构
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("aa");
                e.onNext("bb");
                e.onNext("cc");
                e.onNext("dd");
                e.onComplete();
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String value) {
                Log.i("result:",value);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

偷懒写法一:


            Observable.just("aa","bb","cc","dd")
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String value) throws Exception {
                        Log.i("result:",value);
                    }
                });

偷懒写法二:

 
        String[] arr = {"aa","bb","cc","dd"};
        Observable.fromArray(arr)
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String value) throws Exception {
                        Log.i("result:",value);
                    }
                });

在偷懒写法中just()或者fromArray()内部已经帮我们封装好了一些操作。我们只需要传入相应的内容,在这些方法内部已经帮我们写好了onComplete(),最后可以直接在accept()中接收到发射过来的结果。

异步操作,线程之间的切换

在开发当中只要不是静态页面,我们都要对后台服务器发起网络请求。

众所周知,发起网络请求是一个耗时操作,一般的耗时操作都必须开启一个子线程来进行请求,从网络端拿到数据之后我们要将数据set到各种UI控件中去。但是坑爹的是,在子线程之中我们并不能更新UI,必须在主线程(又称UI线程)进行数据的set,因此我们又必须切换到主线程去做处理。这样一会儿子线程,一会儿主线程的切换处理,非常让人头疼,代码往往是东一点西一点的写,后期不要说维护了,就是自己看都看不懂。但是有了RxJava这个神器,线程之间的切换变得异常的简单且看起来简便。

默认情况下,RxJava和Handler一样,保持着线程不变原则。在哪个线程实例化就跟哪个线程绑定,即如果在主线程实例化则跟主线程绑定,如果在子线程实例化则跟子线程绑定。如果需要进行线程之间的切换,那么就要使用调度器Scheduler。

schedule默认有以下几个线程切换方法:

  • schedule.newThread():直接开启一个新的线程。

  • schedule.io():顾名思义,开启一个io线程,完成对网络请求和文件读写数据库增删改查等操作。可能这时候有人就要问了,那io和newThread有什么区别呐?其实区别在于,newThread不管有没有线程,他都会去重新开启一个新的线程来进行操作,并且没线程池维护。但是io的线程是无上限的,并且最大的一个好处是它会去重用空闲的线程,而不是每次都开启一个线程来使用,效率上比newThread要高。所以,一般我们在使用的时候是直接使用io这个方法。

  • android有一个专门的线程,AndroidSchedule.mainThread(),专门用来指定操作在主线程完成。

有了上面的几个线程操作的知识,我们就可以开始自由的对线程进行操作了。

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {

                Log.i("currentThread111:",Thread.currentThread().getName());
                e.onNext("abcdefg");

            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String value) throws Exception {
                        Log.i("currentThread222:",Thread.currentThread().getName());

                    }
                });
结果:
      I/currentThread111:: RxNewThreadScheduler-1
      
      I/currentThread222:: main
     

可以看到两者进行了线程的切换。上游被观察者处在新的子线程中进行操作,而下游的观察者处理main的主线程进行了操作。

我们在对线程进行切换的时候依靠两个方法。

subscribeOn(): 这个方法指定了Observable被观察者在哪个线程执行。

observeOn(): 这个方法制定了观察者在哪个线程中执行。

拥有了这两个方法,再加上schedule操作线程,我们便可以把耗时的网络操作放在子线程中进行操作了,然后将获取到的json字符串直接通过onNext()方法发送给观察者observe,让他在主线程进行数据的更新操作。再加上RxJava是链式结构操作,我们代码看上去一目了然,再也不是东一下西一下的乱来了。

如果你觉得这就是RxJava全部内容,那你就太小看RxJava了。线程之间的切换只能说是他强大功能中的牛刀小试而已。他真正强大的是他无敌一般存在的各种操作符,拥有了这些操作符,你几乎可以干很多你之前需要大把代码并且写起来极其复杂的逻辑才能完成的功能了。并且依然遵循着他自身特点,操作简单、观看简洁的特点。后续将逐一来写RxJava的各种操作符,并写明操作符可以在哪些场景使用。

有兴趣可以关注我的小专栏,学习更多知识:小专栏