rxjava要点简介

版权声明: https://blog.csdn.net/henysugar/article/details/83347901

rxjava用来干什么

举例子吧。

某个地方不定期地发放个人娱乐用品,小张喜欢这些用品,希望每次都能被通知过来领取享受一把。

rxjava就是能让小张实现愿望的一个社团机构。

在以上的例子中,rxjava负责以下工作:

1.主动发起发放娱乐用品活动,每次都由rxjava主办;

2.每次搞活动时候,rxjava都派人通知小张过来领取当场享受;

所以,切回程序框架的角度,

rxjava可以用来实现这种需求场景:针对连续多次发生的事情或者多个数据进行分发给参与者处理

例如100个图片文件的读取,每读取完一个文件后就调用参与者处理函数进行处理,参与者可能会拿着图片文件进行显示,也可能拿着文件保存到别的地方。

rxjava的特点

前面说的,仅仅是rxjava的功能,rxjava的优点肯定不仅仅是表面功能那么简单。

如果仅仅是对于多次发生的事情分发给参与者处理,那简单地用循环调用参与者的处理函数就ok了,何必用rxjava? 

在此,特介绍一下rxjava的特点:

1.异步的便捷实现;

例如很简单就能实现数据读取过程在某个线程,而参与者处理数据又在另外的线程,或者在ui线程。

2.代码编写易读性;

使用起来的接口调用过程容易阅读和理解,方便后期维护。

3.数据源变换方便;

例如数据源是整数,但是订阅者需要处理的是字符串,通过rxjava可以便捷地做变换。

rxjava要点记录

创建事件源的不同方法

  • 直接提供实现函数

参考下面例子,直接提供一个OnSubscribe回调实现:

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("1");
        subscriber.onNext("2");
        subscriber.onNext("3");
        subscriber.onCompleted();
    }
});
  • just

直接通过参数提供数据源来发生事件(每项数据一次事件)。

看例子:

Observable observable = Observable.just("1", "2", "3");
  • from

从数组或者序列中提供数据源来发生事件(每项数据一次事件)。

abservable.subscribe的理解

注:函数名修改为“abservable.subscribedBy()”可能更好理解。

使用时候这么写:

Observable.from(names).subscribe(subscriber);

意思是:subscriber向abservable进行subscribe,而不是abservable向subscriber进行subscribe。

也就是订阅者向提供方进行订阅动作,此时提供方会内部遍历事件/数据,依次提供给订阅者参与处理。

异步线程处理

rx提供的线程:

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

例子:

Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
    .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
    .subscribe(subscriber);

map

用map的原因:

数据源类型和订阅者处理数据类型如果一致,这样就行:

Observable.just(1, 2, 3, 4)
    .subscribe(new Action1<Integer>() {
        public void call(Integer number) {
            log("number:" + number);
        }
    });

但是,如果遇到数据源类型和订阅者期望处理的类型不一样,就需要一个转换。

map就是为了帮忙转换而被设计出来,map在此的意思是,把数据源类型映射转换为新类型。

例如上面的例子中订阅者希望处理的是字符串,用map转换一下:

Observable.just(1, 2, 3, 4)
    .map(new Func1<Integer,String>(){
        public String call(Integer value){return Integer.toString(value);}
    })
    .subscribe(new Action1<String>() {
        public void call(String number) {
            log("number:" + number);
        }
    });

flatMap和map差异

map针对的是:一一对应地把数据源每一项数据转换为指定的类型,然后给订阅者享用。

如果,订阅者比较懒,希望处理的是每项数据里面的N项子数据,那怎么办? 

例如,某个情景下订阅者处理的是每个人员姓名,那么只需用map(人员,姓名)这种方式,

某天,订阅者突然改变注意,希望处理每位人员的借阅的每一本书,这时候map就搞不定了,因为map只能一一对应地转换,没法一换多。

这时候flatMap就可以帮忙解决这个问题了。

看代码:

TPerson[] personlist = {... 演示忽略...};
Subscriber<Book> subscriber = new Subscriber<Book>() {
    public void onNext(Book book) {
        // do sth...
    }
};

Observable.from(personlist)
    .flatMap(new Func1<TPerson, Observable<Book>>() {
        public Observable<Course> call(TPerson person) {
            return Observable.from(person.getBooks());
        }
    })
    .subscribe(subscriber);

从代码中可以看出,faltMap的原理,其实是把数据源的每一项展开为一个子数据源,然后再给订阅者享用。

“把数据源的每一项展开为一个子数据源”这个过程,rxjava作者认为是一个“flat”的过程,所以叫flatMap。

本文结束。

猜你喜欢

转载自blog.csdn.net/henysugar/article/details/83347901