谈到 RxJava,大家必定不陌生,今天就来大致讲讲关于RxJava1.x的相关知识吧,本篇文章的理解参考以下链接:
给 Android开发者的RxJava详解:http://gank.io/post/560e15be2dca930e00da1083
大家有兴趣的可以看看。
首先,来说说 RxJava 到底是用来干嘛的,为什么要用他?
简单的说来,RxJava是为了实现异步,用他是因为它实现起异步操作简单明了。
然后,我们来说说 RxJava1.x 的实现原理。
R下Java是对观察者模式的扩展,它有四个概念:
1.Obervable----被观察者
2.observer -----观察者
3.subscribe ----订阅
4.事件
RxJava的事件回调包括三个:
onCompleted() ------------ 事件队列完结。RxJava 不仅把每个是事件单独处理,还把它们看作一个队列,当不再有新的 onNext()执行时,会触发此方法。
onError() -------------------- 事件队列异常。在事件处理异常中,触发此方法,同时队列自动中止,不允许再有事件发出。
需要注意的是,再一个正确运行的事件序列中,onCompleted 和 onError 有且只有一个,并且是最后一个触发。onCompleted 和 onError 是互斥的,在对列结尾只能有其中的一个
RxJava 的基本实现。
1.创建观察者 observer
Observer<String>observer=new Observer<String>() {
@Override
public void onNext(String s) {
LogUtil.e("====onNext===s="+s);
}
@Override
public void onCompleted() {
LogUtil.e("====onCompleted======");
}
@Override
public void onError(Throwable e) {
}
};
RxJava内置 Subscriber 实现 Observer 抽象类,其使用方法和 Observer 一样:
Subscriber<String>subscriber=new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
}
};
Observer 和 Subscriber 的区别:
Subscriber 是对 Observer 的扩展,在其基础上多增加了两个方法,onSatrt() 和 unSubscriber()方法
onStart() ---- 在事件发出之前被调用,可以执行一些准备工作,如数据清零或重置,不能对准备工作的线程有要求(例如更新界面ui只能在主线程中执行,onstart就不实用 了),并且 onstart 方法是一个可选方法,默认实现是为空的
unSubscriber() 取消订阅,在这个方法被调用后,Subscriber 将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed() 先 判断一下状态。 unsubscribe() 这个方法很重要,因为在subscribe() 之后, Observable 会持有 Subscriber 的引用,这个引用 如果不能及时被释放,将有内存泄露的风险。所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例 如 onPause() onStop() 等方法中)调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。
2.创建 被观察者 Observable
它决定什么时候触发事件以及触发什么样的事件,Rxjava 用 create()方法来创建一个 Observale,并为他定义事件触发规则
//被观察者
Observable<String>observable=Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hi");
subscriber.onNext("hello");
subscriber.onCompleted();
}
});
可以看到,这里传入了一个 OnSubscribe 对象作为参数。OnSubscribe 会被存储在返回的 Observable 对象中,它的作用相当于一个计划表,当 Observable 被订阅的时候,OnSubscribe 的 call() 方法会自动被调用,事件序列就会依照设定依次触发(对于上面的代码,就是观察者Subscriber 将会被调用三次 onNext() 和一次 onCompleted())。这样,由被观察者调用了观察者的回调方法,就实现了由被观察者向观察者的事件传递,即观察者模式
onCreate()方法是 RxJava 最基本的创建事件序列的方法,RxJava还提供 快捷创建事件序列的方法,如:
1.Jast(T...); 将传入的参数一次发送进来
Observable observable = Observable.just("Hello", "Hi", "Aloha");
// 将会依次调用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
2.from(T[ ]) 或者 from ( Iterable < ? extends T> ) : 将传入的数组或 iterable 拆分成具体对象后,依次发送出来
String[] words = {"Hello", "Hi", "Aloha"};
Observable observable = Observable.from(words);
// 将会依次调用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
上边两个创建方法和 oncreate()方法是等价的
3. Subscribe 订阅
创建 observable(被观察者)和 observer(观察者)后,再用 subscribe()联系起来就能工作了,实现起来形式简单
observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);
除了 observable.subscribe(observer) 和 observable.subscribe(subscriber); 之外,Rxjava 还支持不完整定义的回调,如:
Action1<String> onNextAction = new Action1<String>() {
// onNext()
@Override
public void call(String s) {
Log.d(tag, s);
}
};
Action1<Throwable> onErrorAction = new Action1<Throwable>() {
// onError()
@Override
public void call(Throwable throwable) {
// Error handling
}
};
Action0 onCompletedAction = new Action0() {
// onCompleted()
@Override
public void call() {
Log.d(tag, "completed");
}
};
// 自动创建 Subscriber ,并使用 onNextAction 来定义 onNext()
observable.subscribe(onNextAction);
// 自动创建 Subscriber ,并使用 onNextAction 和 onErrorAction 来定义 onNext() 和 onError()
observable.subscribe(onNextAction, onErrorAction);
// 自动创建 Subscriber ,并使用 onNextAction、 onErrorAction 和 onCompletedAction 来定义 onNext()、 onError() 和 onCompleted()
observable.subscribe(onNextAction, onErrorAction, onCompletedAction);
Action0 ----- Rxjava 的一个接口,无参无返回值,内部只有一个call()方法
Action1 ----- 也是Rxjava的内置接口,有一个参数,无返回值,内部只有一个方法 call(T param)
当然 Rxjava 中还有很多 Action,如Action2,Action3 等
RxJava 的默认规则是 observable 和 observer 在同一线程中,而观察者模式的目的是实现异步,即后台处理,前台回调,于是需要用到 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。
另外, Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
有了这几个 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制了。 * subscribeOn(): 指定subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。 * observeOn(): 指定Subscriber 所运行在的线程。或者叫做事件消费的线程。
代码如下:
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer number) {
Log.d(tag, "number:" + number);
}
});
4.变换
这是 RxJava 的又一个特色,首先来感受下
Observable.just("images/logo.png") // 输入类型 String
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String filePath) { // 参数类型 String
return getBitmapFromPath(filePath); // 返回类型 Bitmap
}
})
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) { // 参数类型 Bitmap
showBitmap(bitmap);
}
});
这里的 Func1 和 前面提到的 Action1 非常相似,也有众多的 FuncX,Func 和 Action 的区别是,Action 无 返回值,而 Func 有。
上面还用到 Observable 的 map()方法,其作用是事件对象的直接转换,还有一个 flatMap()方法,大家可以参照上面我提到的链接去看其具体运用,这里就不细说了
Scherduler
前面已经提过 subscribeOn()和 observeOn()可以对线程切换加以控制,那能多次切换线程吗?
答案是能。observeOn() 指定的是它之后的操作所在的线程。因此如果有多次切换线程的需求,只要在每个想要切换线程的位置调用一次 observeOn() 即可。上代码:
Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新线程,由 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 线程,由 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主线程,由 observeOn() 指定
如上,通过 observeOn() 的多次调用,程序实现了线程的多次切换。
不过,不同于 observeOn() , subscribeOn() 的位置放在哪里都可以,但它是只能调用一次的。
当使用多个 subscribeOn()时,只有第一个有效果。
延伸:doOnSubscribe()
然而,虽然超过一个的 subscribeOn() 对事件处理的流程没有影响,但在流程之前却是可以利用的。
在前面讲 Subscriber 的时候,提到过 Subscriber 的 onStart() 可以用作流程开始前的初始化。然而 onStart() 由于在 subscribe() 发生时就被调用了,因此不能指定线程,而是只能执行在 subscribe() 被调用时的线程。这就导致如果 onStart() 中含有对线程有要求的代码(例如在界面上显示一个 ProgressBar,这必须在主线程执行),将会有线程非法的风险,因为有时你无法预测 subscribe() 将会在什么线程执行。
而与 Subscriber.onStart() 相对应的,有一个方法 Observable.doOnSubscribe() 。它和 Subscriber.onStart() 同样是在 subscribe()调用后而且在事件发送前执行,但区别在于它可以指定线程。默认情况下, doOnSubscribe() 执行在 subscribe() 发生的线程;而如果在 doOnSubscribe() 之后有 subscribeOn() 的话,它将执行在离它最近的 subscribeOn() 所指定的线程。
示例代码:
Observable.create(onSubscribe)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Action0() {
@Override
public void call() {
progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行
}
})
.subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
如上,在 doOnSubscribe()的后面跟一个 subscribeOn() ,就能指定准备工作的线程了
最后,讲下代码中使用 RxJava1.x 的示例,方便大家参考。
首先,添加 app module 的依赖
//rx
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.2.7'
然后在button点击事件中调用
public void ff(){
//被观察者
Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber){
subscriber.onNext("hi");
subscriber.onCompleted();
}
}).subscribe(new Observer<String>() {
@Override
public void onCompleted(){
LogUtil.e("=====onCompleted=======");
}
@Override
public void onError(Throwable e) {
LogUtil.e("=====onError=======");
}
@Override
public void onNext(String s) {
LogUtil.e("=====onNext=====s=="+s);
}
});
}
今天对于 RxJava1.x 的简单介绍就到这里,谢谢诶。