RxJava

[]RxJava

RxJava是一个实现处理异步操作的库, 比AsyncTask 和Handler处理异步操作都要简洁(逻辑简洁)。

[]RxJava的原理简析

RxJava 的异步实现,是通过一种扩展的观察者模式来实现的。观察者不需要时刻监听被观察者,而是采用注册或者称为订阅的方式,告诉被观察者:我需要你的某种状态,你要在状态变化的时候通知我。

RxJava 有四个基本概念:Observable (被观察者), Observer (观察者),subscribe (订阅),事件。被观察者(Observable)和观察者(Observer)通过subscribe()实现订阅关系,从而Observable可以在需要的时候发出事件来通知Observer。

[]观察者(Observer)

观察者决定事件触发的时候将有怎样的行为。

Observer的实现方式

Observer<String> observer = new Observer<String>() {

    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(String s) {

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
};

除了Observer接口实现之外,Subscriber接口也能实现。

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

    @Override
    public void onSubscribe(Subscription s) {
        //执行请求
        s.request(Long.MAX_VALUE);
    }

    @Override
    public void onNext(String s) {

    }

    @Override
    public void onError(Throwable t) {

    }

    @Override
    public void onComplete() {

    }
};

onSubscribe(Disposable d)或者onSubscribe(Subscription s):事件还未发送之前被调用,可以用于做一些准备工作。参数d可用于取消订阅,参数s可用于请求数据(如果不调用请求,Subscriber的onNext()与onComplete()不会被调用)或者取消订阅。

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

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

一个正确运行的事件序列中, onComplete()和onError()有且只有一个,并且是事件序列中的最后一个。

需要注意的是,onComplete()和onError()二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。

[]被观察者(Observable)

被观察者决定什么时候触发事件以及触发怎样的事件。

Observable的实现方式

Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {

    @Override
    public void subscribe(ObservableEmitter<String> e) throws Exception {

        e.onNext("hello");
        e.onNext("hi");
        e.onNext("ye");
        e.onComplete();

    }
});

除了Observable接口实现之外,Flowable抽象类也能实现。

Flowable<String> flowable = Flowable.create(new FlowableOnSubscribe<String>() {

    @Override
    public void subscribe(FlowableEmitter<String> e) throws Exception {
        e.onNext("hello");
        e.onNext("hi");
        e.onNext("ye");
        e.onComplete();
        }
        //需要指定背压策略
}, BackpressureStrategy.BUFFER);

当被观察者被订阅的时候,subscribe()会自动被调用,事件序列就会依照设定依次触发(会被调用三次onNext()和一次onComplete())。这样,由被观察者调用了观察者的回调方法,就实现了由被观察者向观察者的事件传递,即观察者模式。

RxJava 还提供了其它快捷方式来创建事件队列。

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

Observable<String> observable = Observable.just("hello", "hi", "ye");
    // 将会依次调用
    // onNext("Hello");
    // onNext("Hi");
    // onNext("ye");
    // onCompleted();

fromArray():传入的数组拆分成具体对象后,依次发送出来。

String[] items = {"Hello", "Hi", "ye"};
Observable<String> observable = Observable.fromArray(items);
    // 将会依次调用
    // onNext("Hello");
    // onNext("Hi");
    // onNext("ye");
    // onCompleted();

还有fromIterable()等等。

[]订阅(Subscribe)

Subscribe的实现方式

 observable.subscribe(observer); 或者
 flowable.subscribe(subscriber);

Observeable用于订阅Observer,是不支持背压,而Flowable用于订阅Subscriber,是支持背压(Backpressure)。

背压:是指在异步场景中,被观察者发送事件速度远快于观察者的处理速度的情况下,一种告诉上游的被观察者降低发送速度的策略。没有背压可能会导致MissingBackpressureException。

使用Observable/Observer的时候,需要考虑的是,数据量是不是很大(官方给出以1000个事件为分界线,仅供各位参考)。

subscribe() 还支持不完整定义的回调。RxJava会自动根据定义创建出 Observer。

不完整回调的实现方式:

Consumer nextConsumer = new Consumer() {
    @Override
    public void accept(@NonNull Object o) throws Exception {

    }
};

Consumer errConsumer = new Consumer() {
    @Override
    public void accept(@NonNull Object o) throws Exception {

    }
};

Action completeAction = new Action() {
    @Override
    public void run() throws Exception {

    }
};

// 自动创建Observer,并使用nextConsumer,errConsumer和completeAction
来定义onNext(),onError()和onCompleted()

observable.subscribe(nextConsumer, errConsumer, completeAction);

[]调度器(Scheduler)——线程控制

在不指定线程的情况下, RxJava遵循的是线程不变的原则,即在哪个线程调用subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到Scheduler。

Scheduler:相当于线程控制器,RxJava通过它来指定每一段代码应该运行在什么样的线程。

RxJava提供的Scheduler

Schedulers.newThread():启用新线程来执行操作。

Schedulers.io():I/O 操作(读写文件,读写数据库,网络信息交互等)使用的Scheduler。它的内部是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下io() 比newThread()更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。

Schedulers.computation():计算使用的Scheduler。这个计算指的是 CPU密集型计算,即不会被 I/O等操作限制性能的操作,例如图形的计算。这个 Scheduler使用固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在computation()中,否则 I/O 操作的等待时间会浪费 CPU。

AndroidSchedulers.mainThread():Android指定在主线程进行操作。

使用subscribeOn()和observeOn()来对线程进行控制。

subscribeOn():指定subscribe()发生的线程,Observable运行在的线程,或者叫做事件产生的线程。
observeOn():指定Observer运行在的线程。或者叫做事件消费的线程。

Observable.just(1, 2, 3, 4, 5, 6)
    //指定subscribe()发生在IO线程
    .subscribeOn(Schedulers.io()) 

    //指定Observer的回调发生在主线程  
    .observeOn(AndroidSchedulers.mainThread()) 

    .subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {

        }
});

多次切换线程:observeOn()的多次调用

observeOn()指定的是Observer的线程,而这个Observer并不是subscribe() 参数中的Observer,而是observeOn() 执行时的当前Observable所对应的 Observer,即它的直接下级Observer。简单的来说,observeOn() 指定的是它之后的操作所在的线程。

因此在每个想要切换线程的位置调用一次observeOn()就可多次切换线程。

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

subscribeOn() 的位置放在哪里都可以,但它是只能调用一次的。

Observable对象的doOnSubscribe():

是在subscribe()调用后并且在事件发送前执行,默认情况下,doOnSubscribe()执行在subscribe()发生的线程,而如果在doOnSubscribe()之后有subscribeOn(),它将执行在离它最近的subscribeOn()所指定的线程。

Observable.just("1", "2", "3", "4")
    .subscribeOn(AndroidSchedulers.mainThread())
    .doOnSubscribe(consumer)//新线程,由subscribeOn()指定
    .subscribeOn(Schedulers.newThread())
    .observeOn(Schedulers.io())
    .subscribe(consumer);

[]变换操作

变换:就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。

map():事件对象的直接变换并返回。用于一对一的转化。

Observable.just("logo.png") //输入类型String
        .map(new Function<String, Bitmap>() {
            @Override
            public Bitmap apply(@NonNull String s) throws Exception {//参数类型String 返回类型Bitmap 
                return null;
            }
        }).subscribe(new Consumer<Bitmap>() {
    @Override
    public void accept(@NonNull Bitmap bitmap) throws Exception { //参数类型位为Bitmap 

        }
    });

map()将参数中的String转换成一个Bitmap后返回,而经过map()后,事件的参数类型也由String转为了Bitmap。

flatMap():用于一对多的转化。 也常用于嵌套的异步操作。

Observable.fromIterable(stuList)
    .flatMap(new Function<Student, ObservableSource<Course>>() {
        @Override
        public ObservableSource<Course> apply(@NonNull Student student) throws Exception {
            return Observable.fromIterable(student.getCourseList());
        }
    })
    .subscribe(new Consumer<Course>() {
        @Override
        public void accept(@NonNull Course course) throws Exception {

        }
    });

flatMap()和map()都是把传入的参数转化之后返回另一个对象。但是flatMap() 中返回的是个ObservableSource,并且这个ObservableSource并不是被直接发送到了Observer的回调方法中。

flatMap()的原理

  1. 使用传入的事件对象创建一个ObservableSource。
  2. 并不发送这个ObservableSource,而是将它激活,于是它开始发送事件。
  3. 每一个创建出来的ObservableSource发送的事件,都被汇入同一个 Observable,而这个Observable负责将这些事件统一交给Observer的回调方法。

    RxJava 还提供很多便捷的方法来实现事件序列的变换。

flatMapIterable(Function mapper):

switchMap(Function mapper):

scan(BiFunction accumulator):

[]过滤操作

filter(Predicate predicate):过滤不满足条件的值。

take(long count):获取前面的count个对象。

takeLast(int count):获取后面的count个对象。

skip(long count):忽略前面的count个对象。

skipLast(int count):忽略后面的count个对象。

elementAt(long index):获取第index的对象。

distinct(Function keySelector):过滤掉重复的值。

first(T defaultItem):获取第一个对象。

last(T defaultItem):获取最后一个对象。

[]组合操作

相关文章

给 Android 开发者的 RxJava 详解
http://gank.io/post/560e15be2dca930e00da1083#toc_30

RxJava系列
https://zhuanlan.zhihu.com/p/20687178

ReactiveX/RxJava文档中文版
https://mcxiaoke.gitbooks.io/rxdocs/content/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值