RxJava

RxJava是ReactiveX的一种Java实现。ReactiveX是Reactive Extensions的缩写,一般简写为Rx。开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流,用Schedulers参数化异步数据流的并发处理,Rx可以这样定义:Rx = Observables + LINQ + Schedulers。

  • 或许你会问:我为什么要选择RxJava ?
一般我们在开发的时候,只要说到异步操作,就会想到Android的AsyncTask和Handler。但是随着请求的数量越来越多,
代码逻辑将会变得越来越复杂,而RxJava却仍旧能保持清晰的逻辑。RxJava的原理就是创建一个Observable对象来干活,
然后使用各种操作符建立起来的链式操作,就如同流水线一样,把你想要处理的数据一步一步加工成你想要的成品,
然后发射给Subscriber处理。
  • RxJava与观察者模式
RxJava的异步操作是通过扩展的观察者模式来实现的。RxJava有4个角色:Observable、Observer、Subscriber和Suject。
Observable和Observer通过subscribe方法实现订阅关系,Observable就可以在需要的时候通知Observer。
  • RxJava的实现

在使用RxJava前请先在AndroidStudio配置gradle:(此处以RxJava为例,不使用RxJava2)

dependencies {
    ...

    compile 'io.reactivex:rxjava:1.2.0'
    compile 'io.reactivex:rxandroid:1.2.1'
}

看到这里可能会问:我使用的是RxJava,为什么还要引入RxAndroid ?

RxAndroid是RxJava在Android平台的扩展。包含了一些能够简化Android开发的工具,比如特殊的调度器。

  • RxJava的使用

RxJava的使用可以分为3个步骤:创建Observable(被观察者)、创建Observer(观察者)、Subscribe(订阅)。

创建Observable(被观察者)

Observable它决定什么时候触发事件以及触发怎样的事件。RxJava使用 create 方法来创建一个Observable,并未它定义时间触发规则。例如:

        // 创建Observable(被观察者)
        Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("张三");
                subscriber.onNext("李四");
                subscriber.onCompleted();
            }
        });

通过调用Subscriber的方法,不断的将事件添加到任务队列中。

创建Observer(观察者)

Observer 它决定事件触发的时候将有怎么样的行为。

        // 创建Observer(观察者)
        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onStart() {
                Log.e(TAG, "onStart");
            }

            @Override
            public void onCompleted() {
                Log.e(TAG, "onCompleted");
            }

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

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

其中,onCompleted、onError和onNext是必须要实现的方法。其具体含义如下:

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

  • onError:事件队列异常。在事件处理过程中出现异常时,onError() 方法会被触发,同时队列自动终止,不允许再有事件发出。

  • onNext():普通的事件。将要处理的事件添加到事件队列中。

  • onStart():它会在事件还未发送之前被调用,可以用于做一些准备工作。例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。

当然,如果要实现简单的功能,也可以用到Observer来创建观察者。Observer是一个接口,而上面用到的Subscriber是在Observer的基础上进行的扩展。在后文的Subscribe订阅过程中Observer也会被转换为Subscriber来使用。如果用Observer创建观察者对象,如下:

Observer<String> observer = new Observer<String>() {
            @Override
            public void onCompleted() {
                Log.e(TAG, "onCompleted");
            }

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

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

Subscribe(订阅)

observable.subscribe(subscriber);

运行代码可查看Log:

E/RxJavaActivity: onStart
E/RxJavaActivity: onNext张三
E/RxJavaActivity: onNext李四
E/RxJavaActivity: onCompleted

RxJava操作符

RxJava操作符类型可以分为:创建操作符、变换操作符、过滤操作符、组合操作符、错误处理操作符、辅助操作符、条件和布尔操作符、算术和聚合操作符及连续操作符等,而这些操作符类型下又有很多操作符,每个操作符可能还有很多变体。此处,简单的介绍一些创建操作符、变换操作符、过滤操作符、辅助操作符、错误处理操作符。

创建操作符

  • Interval

创建一个按固定时间间隔发射整数序列的Observable,相当于定时器,如下:

Observable.interval(3, TimeUnit.SECONDS)
                .subscribe(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {
                        Log.e(TAG, "interval:" + aLong.intValue());
                    }
                });

上面的代码每个3s就会调用call方法并打印Log。

  • Range

创建发射指定范围的整数序列的Observable,可以拿来代替for循环,发射一个范围内的有序整数序列。第一个参数是起始值,并不小于0;第二个参数为整数序列的个数。

Observable.range(0, 5)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.e(TAG, "range:" + integer.intValue());
                    }
                });

运行代码可查看Log:

E/RxJavaActivity: range:0
E/RxJavaActivity: range:1
E/RxJavaActivity: range:2
E/RxJavaActivity: range:3
E/RxJavaActivity: range:4
  • Repeat

创建一个N次重复发射特定数据的Observable,如下:

Observable.range(0, 3)
                .repeat(2)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.e(TAG, "repeat:" + integer.intValue());
                    }
                });

运行代码可查看Log:

E/RxJavaActivity: repeat:0
E/RxJavaActivity: repeat:1
E/RxJavaActivity: repeat:2
E/RxJavaActivity: repeat:0
E/RxJavaActivity: repeat:1
E/RxJavaActivity: repeat:2

变换操作符

  • Map

map操作符通过指定一个Func对象,将Observable转换为一个新的Observable对象并发射,观察者将收到最新的Observable处理。例如:

final String host = "https://github.com/";
        Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {

                subscriber.onNext("JiaYang627");
            }
        }).map(new Func1<String, String>() {
            @Override
            public String call(String s) {
                return host + s;
            }
        }).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.e(TAG, "map:" + s);
            }
        });

运行代码查看Log:

E/RxJavaActivity: map:https://github.com/JiaYang627

过滤操作符

  • Filter

Filter操作符是对源Observable产生的结果自定义规则进行过滤,只有满足条件的结果才会交给订阅者。例如:

 Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                subscriber.onNext(1);
                subscriber.onNext(2);
                subscriber.onNext(3);
                subscriber.onNext(4);

            }
        }).filter(new Func1<Integer, Boolean>() {
            @Override
            public Boolean call(Integer integer) {
                return integer > 2;
            }
        }).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.e(TAG, "filter:" + integer);
            }
        });

运行代码查看Log:

E/RxJavaActivity: filter:3
E/RxJavaActivity: filter:4

辅助操作符

  • Do

Do系列操作符是为原始Observable的生命周期事件注册一个回调,当Observable的某个事件发生时就会调用这些回调。RxJava中有很多Do系列操作符,如下:

  • doOnEach:为Observable注册这样一个回调:当Observable每当发射一项数据时就会调用它一次,包括onNext、onError和onCompleted。
  • doOnNext:只有执行onNext的时候会被调用。
  • doOnSubscribe:当观察者订阅Observable时就会被调用。
  • doOnUnsubscribe:当观察者取消订阅Observable时就会被调用;Observable通过onError或者onCompleted结束时,会取消订阅所有的Subscriber。
  • doOnCompleted:当Observable正常终止调用onCompleted时会被调用。
  • doOnError:当Observable异常终止调用onError时会被调用。
  • doOnTerminate:当Observable终止(无论是正常终止还是异常终止)之前会被调用。
  • finallyDo:当Observable终止(无论是正常终止还是异常终止)之后会被调用。

此处以doOnNext为例,如下:

 Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                subscriber.onNext(1);
                subscriber.onNext(2);
            }
        }).doOnNext(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.e(TAG, "doOnNext:" + integer);
            }
        }).subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

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

运行代码查看Log:

E/RxJavaActivity: doOnNext:1
E/RxJavaActivity: subscribe_onNext:1
E/RxJavaActivity: doOnNext:2
E/RxJavaActivity: subscribe_onNext:2
  • SubscribeOn、ObserverOn

SubscribeOn操作符用于指定Obserable自身在哪个线程上运行。如果Observable需要执行耗时操作,一般可以让其在新开的一个子线程上运行。ObserverOn用来指定Observer所运行的线程,也就是发射出的数据在哪个线程上使用。一般情况下会指定砸死主线程中运行,这样就可以修改UI。如下:

 Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                Log.e(TAG, "Observable:" + Thread.currentThread().getName());
                subscriber.onNext(1);
            }
        }).subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(new Action1<Integer>() {
              @Override
              public void call(Integer integer) {
                  Log.e(TAG, "Observer:" + Thread.currentThread().getName());
              }
          });

运行代码查看Log:

E/RxJavaActivity: Observable:RxIoScheduler-2
E/RxJavaActivity: Observer:main

其中,AndroidSchedulers是RxAndroid库中提供的Scheduler。

错误处理操作符

  • Retry

Retry操作符不会将原始Observable的onError通知传递给观察者,它会订阅这个Observable再给它一次机会无错误地完成其数据序列。Retry总是传递onNext通知给观察者,由于重新订阅,这可能会造成数据项重复。RxJava中的实现为Retry和RetryWhen。此处以Retry为例说明。

它指定最多重新订阅的次数,如果次数超了,它不会尝试再次订阅,而会把最新的一个onError通知传递给自己的观察者。如下:

Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                for (int i =0 ; i < 5 ; i ++) {
                    if (i == 1) {
                        subscriber.onError(new Throwable("Throwable"));
                    } else {
                        subscriber.onNext(i);
                    }
                }
            }
        }).retry(2)
          .subscribe(new Subscriber<Integer>() {
              @Override
              public void onCompleted() {
                  Log.e(TAG, "onCompleted");
              }

              @Override
              public void onError(Throwable e) {
                  Log.e(TAG, "onError:" + e.getMessage());
              }

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

如上所示,Observable中走了一个for循环,当i为0时走onNext,当i为1时让走onError,然后,此时会重新订阅,再次走for循环,此为第一次重新订阅。在第二次重新订阅的时候,走到onError后不会再次重新订阅,运行代码查看Log:

E/RxJavaActivity: onNext:0
E/RxJavaActivity: onNext:0
E/RxJavaActivity: onNext:0
E/RxJavaActivity: onError:Throwable

RxJava结合Retrofit访问网络

此处使用自己写的MVP框架Demo为例,使用的是RxJava2、Retrofit2。

  • 首先配置build.gradle:
dependencies {
    ...
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.1.0'
    
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    compile 'org.ligboy.retrofit2:converter-fastjson-android:2.1.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
    
    compile 'com.alibaba:fastjson:1.2.33'

}

以上为配置依赖,Demo中使用FastJson数据解析。

配置Retorfit:

private Retrofit creatRetrofit(Retrofit.Builder builder, String baseUrl, OkHttpClient client){
        builder.client(client)
                .baseUrl(baseUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(FastJsonConverterFactory.create());
        return builder.build();
    }
  • 注意:由于MVP框架使用的是Dagger2 + RxJava2 + Retrofit2 + OkHttp3 + FastJson。此处只说配置Retrofit。

上面配置Retrofit的时候,添加 addCallAdapterFactory方法,这样此前Retrofit定义的接口返回的就不是Call了,而是Observalbe,这样就能用RxJava提供的方法来对请求网络的回调进行处理。添加的addConverterFactory方法支持对返回结构的支持类型,此处支持的为FastJson 和String类型。

最后,给出MVP框架的地址,此项目框架采用 OkHttp3 + RxJava2 + Retrofit2 + Dagger2 + FastJson 为主体的 mvp框架。里面有详细的Retrofit配置,已经RxJava请求联网时线程转换。

Demo:
MVPFramework

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容