什么是Rx
Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序。简单来讲Rx就是一种
响应式编程,来
创建基于事件的异步程序
RxJava 到底是什么
RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"也就是官方定义:一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。
然而,对于初学者来说,这太难看懂了。因为它是一个『总结』,而初学者更需要一个『引言』。
其实, RxJava 的本质可以压缩为 异步这一个词。说到根上,它 就是一个实现异步操作的库,而别的定语都是基于这之上的。
然而,对于初学者来说,这太难看懂了。因为它是一个『总结』,而初学者更需要一个『引言』。
其实, RxJava 的本质可以压缩为 异步这一个词。说到根上,它 就是一个实现异步操作的库,而别的定语都是基于这之上的。
RxJava 的异步实现,是通过一种扩展的观察者模式来实现的。
观察者模式
- 普通的观察者模式:
其中这个Button就是被观察者(Observable),OnClickListener就是观察者(Observer),两者通过setOnClickListener达成订阅(Subscribe)关系,之后当Button产生OnClick事件的时候,会直接发送给OnClickListener,它做出相应的响应处理。
- RxJava的观察者模式呢,跟这个差不多,但是也有几点差别:
Observer与Observable是通过 subscribe() 来达成订阅关系。
RxJava中事件回调有三种:onNext() 、 onCompleted() 、 onError() 。
如果一个Observerble没有任何的Observer,那么这个Observable是不会发出任何事件的。
RxJava中事件回调有三种:onNext() 、 onCompleted() 、 onError() 。
如果一个Observerble没有任何的Observer,那么这个Observable是不会发出任何事件的。
关于RxJava的回调事件:
- onNext():基本事件。
- onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
- onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
RxJava 好在哪
换句话说,『同样是做异步,为什么人们用它,而不用现成的 AsyncTask / Handler / XXX / ... ?』
异步操作很关键的一点是程序的简洁性,因为在调度过程比较复杂的情况下,异步代码经常会既难写也难被读懂。 Android 创造的 AsyncTask 和Handler ,其实都是为了让异步代码更加简洁。RxJava 的优势也是简洁,但它的简洁的与众不同之处在于,随着程序逻辑变得越来越复杂,它依然能够保持简洁。
异步操作很关键的一点是程序的简洁性,因为在调度过程比较复杂的情况下,异步代码经常会既难写也难被读懂。 Android 创造的 AsyncTask 和Handler ,其实都是为了让异步代码更加简洁。RxJava 的优势也是简洁,但它的简洁的与众不同之处在于,随着程序逻辑变得越来越复杂,它依然能够保持简洁。
如何实现RxJava
- 创建Observer
//1.创建观察者对象
Observer<String> observer=new Observer<String>() {
@Override
public void onCompleted() {
Log.e("kaka","onComlieted");
}
@Override
public void onError(Throwable e) {
Log.e("kaka","onError");
}
@Override
public void onNext(String s) {
Log.e("kaka","onNext");
}
};
- 创建Observable
//2.创建被观察者对象
Observable<String> observable=Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hi");
subscriber.onNext("nihao");
subscriber.onNext("kaka");
subscriber.onCompleted();
}
});
- 现在就需要用 subscribe() 方法来将它们连接起来,形成一种订阅关系:
observable.subscribe(observer);
这里其实确实有点奇怪,为什么是Observable(被观察者)订阅了Observer(观察者)呢?其实我们想一想之前Button的点击事件:
Button.setOnClickListener(new View.OnClickListener())
Button是被观察者,OnClickListener是观察者,setOnClickListener是订阅。我们惊讶地发现,也是被观察者订阅了观察者,所以应该是一种流式API的设计吧,也没啥影响。
线程控制——Scheduler
在RxJava中,Scheduler相当于线程控制器,可以通过它来指定每一段代码运行的线程。
RxJava已经内置了几个Scheduler
Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的Scheduler。
Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的Scheduler。行为模式和newThread()差不多,区别在于io()的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下io()比newThread()更有效率。不要把计算工作放在io()中,可以避免创建不必要的线程。
Schedulers.computation(): 计算所使用的Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个Scheduler使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在computation()中,否则 I/O 操作的等待时间会浪费 CPU。
AndroidSchedulers.mainThread(),Android专用线程,指定操作在主线程运行。(需要导入RxAndroid依赖)
那我们 如何切换线程呢?RxJava中提供了两个方法:subscribeOn() 和 observeOn() ,两者的不同点在于:
subscribeOn(): 指定subscribe()订阅所发生的线程,即 call() 执行的线程。或者叫做事件产生的线程。
observeOn(): 指定Observer所运行在的线程,即onNext()执行的线程。或者叫做事件消费的线程。
RxJava已经内置了几个Scheduler
Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的Scheduler。
Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的Scheduler。行为模式和newThread()差不多,区别在于io()的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下io()比newThread()更有效率。不要把计算工作放在io()中,可以避免创建不必要的线程。
Schedulers.computation(): 计算所使用的Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个Scheduler使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在computation()中,否则 I/O 操作的等待时间会浪费 CPU。
AndroidSchedulers.mainThread(),Android专用线程,指定操作在主线程运行。(需要导入RxAndroid依赖)
那我们 如何切换线程呢?RxJava中提供了两个方法:subscribeOn() 和 observeOn() ,两者的不同点在于:
subscribeOn(): 指定subscribe()订阅所发生的线程,即 call() 执行的线程。或者叫做事件产生的线程。
observeOn(): 指定Observer所运行在的线程,即onNext()执行的线程。或者叫做事件消费的线程。
Observable.just("hi","nihao","woshi")
.subscribeOn(Schedulers.io())//被创建的事件内容"hi","nihao","woshi"将会在io线程发出
.observeOn(AndroidSchedulers.mainThread())//字符串的打印将发生在主线程
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("kaka",s);
}
});
一个基于RxJava的Demo
/**
* 点击按钮,imageview显示图片
*
* @param view
*/
public void downloadImg(View view) {
Observable.create(new Observable.OnSubscribe<Bitmap>() {
@Override
public void call(Subscriber<? super Bitmap> subscriber) {
subscriber.onNext(GetBitmapForUrl.getBitmap(url));//通过URL得到图片的bitmap对象
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Bitmap>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
});
}
运行结果:
几篇关于RxJava的文章:
Rx系列之RxJava操作符:
http://www.jianshu.com/p/30e13d874a61
Rx系列之Rxjava操作符进阶-使用场景:
http://www.jianshu.com/p/79cb4e1c9771