所谓的Rxjava可以理解为异步,他的一切操作都是为了异步,是通过一种拓展的观察者模式实现的。所谓观察者模式,像Android开发中的btn.setOnclickListener(this),这种的就是观察者模式。这里的btn就是被观察者,所处的activity或者fragment就是观察者,说白了就是被观察者给自己设置个与观察者有关联的监听器,用于事件触发后通知观察者。
Rxjava观察者模式
Rxjava基本概念:Observable
(被观察者),Observer(观察者),subscribe
(订阅)事件,Observable(被观察者)与Observer(观察者)通过subscribe进行关联,从而Observable在被观察的事件被触发的时候通知Observer;
Rxjava回调函数里包括:onNext(),onCompleted()和onError();
onNext():相当于onclick(),做一些回调处理。
onCompleted():事件队列完结。Rxjava不仅把每个事件单独处理,还把他们看作一个队列。当最后一个onNext()方法执行结束的时候,就会调用
onCompleted();
onError():事件队列执行异常;在事件执行的过程中出现异常,这个时候触发onError(),同时终止队列,不在允许发布事件,这里要注意一点:
就是onError()和onCompleted()是互斥的,只允许执行一个。
基本使用
1、创建Observer
Observer即观察者,他决定被观察者通知观察者后需要做什么处理,相当于setOnClickListener;
Observer<T> observer = new Observer<T>(){
@Override
public void onNext(T t){
}
@Override
public void onCompleted(T t){
}
@Override
public void onError(T t){
}
};
除了observer之外,Rxjava还内置了一个oberver的抽象类:Subscriber,这个是对oberver做了一些扩展,基本使用没有区别。
Subscriber<T> subscriber= new Subscriber<T>(){
@Override
public void onNext(T t){
}
@Override
public void onCompleted(T t){
}
@Override
public void onError(T t){
}
};
而且oberver在被subscribe的过程中,oberver也会常常被转为Subscriber在使用,他们对于开发者的主要区别有两点:
1、onstart(),这个是subscribe扩展方法,在事件还未发出之前做一些准备工作,总是在subscribe所在的线程执行,不能够指定线程,
所以不适合需要在主线程做操作。若要在指定的线程中做一些操作,可以用doOnSubscribe(),这个后面再说。
2、unsubscribe(),这个方法使用来结束事件的发送,也可以理解释放subscribe的引用。在我们不在使用的时候可以在合适的地方(比如onpause)
调用这个方法对Obervable所持有的subscribe的引用进行释放,这样就不会造成内存泄漏。
2、创建 Observable
Observable即被观察者,Rxjava通过oncreate()进行创建,在里面可以对事件触发规则进行设定。
Observable observable = Observable.Oncreate(new Observable.OnSubscribe<T>()){
@override
public void call(Subscriber<? super T> subscriber){
subscriber.onNext("Hello");
subscriber.onNext("Hi");
subscriber.onNext("Aloha");
subscriber.onCompleted();
}
});
在Observable(被观察者)被订阅的时候,observable被调用,call方法被调用,接着依次执行3次onNext()方法和一次onCompleted()方法。
Rxjava还提供一些快速创建的方法:
just(T...):将参数依次发送出去
Observable observable = Observable.just("Hello","Hi","Aloha");
等同于上面的。
from(T[])/from(Iterable<? extends T>):将传入的数组或 Iterable
拆分成具体对象后,依次发送出来。
String[] words = {"Hello","Hi","Aloha"};
Observable observable = Observable.from(words);
同上。
3、Subscribe (订阅)
有了Observable
和
Observer后,就可以用Subscribe将他们绑定,这样就可以进行工作了。
observable.subscribe(obsever);
这里要说明一点,observable并不是在创建的时候就发送事件,而是在被subscribe绑定后(即subscriber()方法开始执行时)开始事件发送。
不完整定义的回调
Action0是Rxjava的一个接口,里面只有一个方法call,此方法是无参数无返回值的。由于onCompleted()方法也是无参数无返回值的,所以可以将Action0包装传入subscribe。
我的理解是:这个就是用Action0替代Subscriber中的onCompleted()方法。
Action1类似于Action0,不同的是它有一个参数,这样他们就可以用来替代onNext()和onError()。
Rxjava中提供了多个Actionx接口,比如Action2、Action3,我觉得后面的数字就是它所具有的参数的个数(这一点并没有证实,不过按照设计理念来说应该是这样的)。
好了,到这里Rxjava的基本使用已经说完了,不过。。这些并没什么ruan用。因为Rxjava的事件发出和消费默认是在同一个线程执行的,这远远的背离了它异步的初衷,
因此,这要说说两一个概念:Scheduler
。
3、线程控制Scheduler
Scheduler(线程调度器),说白就是Rxjava中对一段代码指定所要运行的线程。Rxjava中内置了几个
Scheduler
,这些已经可以满足大多数的需求了:
Schedulers.immediate()
:这是默认的,就是不指定线程,在当前线程中运行。
Schedulers.newThread()
:这个是启动一个行线程,在这个新线程中执行
Schedulers.io()
:这个和newThread()差不多,不过能不是用一个无数量限制的线程池实现的,可以重用空闲线程,因此要比newThread()更有效率。
但是,不要把在里面进行计算工作,以免建造不必要的线程。
Schedulers.computation()
:用于计算的Scheduler.这个CPU计算是指密集型计算,即不会被I/O操作限制性能的,比如图形计算。这个是用一个固定的线程池实现的,
线程数量等于CPU核数,不要把I/O操作放在这里面,否则I/O的等待时间会浪费CPU
AndroidSchedulers.mainThread():这个是给Android专用的,用于指定到主线程执行。
Observable.just("1","2")
.subscribeOn(Scheduler.io())
.observeOn(AndroidScheculers.mainThread())
.subscribe(new Action1<Interger>()){
@override
public void call(Interger num){
}
});
上面的代码是,被创建的事件由于被subscribeOn()指定,所以事件内容“1”、“2”会在io线程里发送出去。而subscriber
被observeOn()指定,所以call方法会在主线程执行。
这里要说下的是,事件(即被观察者)可以在被创建后用subscribeOn指定线程,但是subscriber
(观察者)必须要在被创建之前被observeOn()指定。
4. 变换
所谓的变换就是对事件或者事件序列进行加工处理,从而得到新的事件或者事件序列。map():事件对象的变换
Observable.just(images/logo.png)
.map(new Func1<String,Bitmap>(){
@override
public Bitmap call(String filePath){
return getBitmapFromPath(filePath);
}
})
.subscribe(new Action1<Bitmap>(){
@override
public void call(Bitmap bitmap){
showBitmap(bitmap);
}
});
Func1和Action1一样也是Rxjava的接口,区别在于Func1有返回值。上面通过map将String类型转换为Bitmap,然后通过subscribe展示。
flatMap()
:这个比较难理解,举个例子:
Student[] students = ...;
Subscirber subscriber = new Subscirber<Course>(){
@override
onNext(Course course){
}
};
Observable.from(students)
.flatMap(new Func1<Student,Observable<Course>>(){
@override
observable<Course> call(Student student){
return Observable.from(student.getCourse);
}
})
.subscribe(subscriber);
上面的代码执行过程是这样的,首先创建参数是Student对象的数组,然后开始执行flatMap方法,而这方法对传入的students进行循环的获取,取出Course并创建Observable对象,
这个对象才是与下面的subscriber匹配的。接着将这样Observable对象依次放入同一个Observable中,相当于把一些对象依次存入集合中,然后统一发出去交给subscriber依次处理,
相当于for循环subscriber中call方法。
以上就是我对flatMap()的理解,我所看的文章的作者叫它为铺平,而我觉得叫它整合更好些,将一组Observable对象进行整合后统一发送。
变换的原理:lift()
Observable
执行了
lift(Operator)
方法之后,会返回一个新的
Observable
,这个新的
Observable
会像一个代理一样,负责接收原始的
Observable
发出的事件,并在处理后发送给
Subscriber
。
就是相当于lift()生成一个新的observable对原始的observable和Subscriber进行关联,在事件触发时,由新observable同志原始observable(如有多层,即上一层),接受原始observable(如有多层,即上一层)处理,然后发送到Subscriber(如有多层,即下一层)。(详细的可以看这篇文章)
compose: 对 Observable 整体的变换
这个是针对 Observable
自身进行变换,我的理解是observable通过N个lift()方法对observable进行转换,最终得到自己想要的处理发送。中间的过程类似于lift()。
5. 线程控制:Scheduler (二)
subscribeOn()指定的是Observable
和
observeOn()指定的是Subscriber线程,它们的切换线程的原理类似于lift()。
subscribeOn()可以在任何位置,并且只能执行一次。由于subscribeOn线程切换发生在OnSubscribe
中,也就是说它在通知上级时,而事件并没有发出去,因此subscribeOn线程控制在事件开端就已经有影响了。
observeOn()由于在内建的(也就是上面说的lift新建的observable对象)Subscriber
进行线程切换,所以它只会对下一个Subscriber
有影响。因此要在Subscriber
发送事件进行设置。
延伸:doOnSubscribe()
doOnSubscribe()
执行在 subscribe()
发生的线程;而如果在 doOnSubscribe()
之后有 subscribeOn()
的话,
subscribeOn()
所指定的线程。(也就是
doOnSubscribe()下面一个subscribeOn())
RxBinding
OnClickListener
、设置
TextWatcher
这样的注册绑定对象的 API。
RxBus
最后
这是我第一次写博客,时间仓促,有很多不足,望见谅。