如下为Rxjava最基础也是最常见的使用样例:
/**
* 最基础的使用
*/
Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> arg0) {
arg0.onNext("Hi");
arg0.onNext("I'm xiaoming");
arg0.onCompleted();
}
}).subscribe(new Subscriber() {
@Override
public void onCompleted() {
Utils.p("结束了!");
}
@Override
public void onError(Throwable arg0) {
Utils.p("出错了!");
}
@Override
public void onNext(Object arg0) {
Utils.p((String) arg0);
}
});
- 如果不在意onError,onFinish的通知,那么subscribe中的Subscriber完全可以直接使用Action1来代替
很典型的观察者模式,Rxjava取名也是名副其实,我来用图来理一下他们的关系。
onError 和 onComplete
与传统观察者模式不同, RxJava 的事件回调方法除了普通事件 onNext() (相当于 onClick() / onEvent())之外,还定义了两个特殊的事件:onCompleted() 和 onError()。
- onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
- onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
- 在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
ActionX, FuncX
- X所代表的数字,表示其包装的call方法里会带有多少参数。
- Func包装的是有返回值的方法,Action则无。
Observer 和 Subscriber
不仅基本使用方式一样,实质上,在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用。所以如果你只想使用基本功能,选择 Observer 和 Subscriber 是完全一样的。它们的区别对于使用者来说主要有两点:
- onStart(): 这是 Subscriber 增加的方法。它会在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。需要注意的是,如果对准备工作的线程有要求(例如弹出一个显示进度的对话框,这必须在主线程执行), onStart() 就不适用了,因为它总是在 subscribe 所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用 doOnSubscribe() 方法,具体可以在后面的文中看到。
- unsubscribe(): 这是 Subscriber 所实现的另一个接口 Subscription 的方法,用于取消订阅。在这个方法被调用后,Subscriber 将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed() 先判断一下状态。 unsubscribe() 这个方法很重要,因为在 subscribe() 之后, Observable 会持有 Subscriber 的引用,这个引用如果不能及时被释放,将有内存泄露的风险。所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例如 onPause() onStop() 等方法中)调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。
defer
defer翻译过来有延迟,推迟之意
defer 和 just,from,create一样,都是产生Observable,但区别在于defer是在有订阅者订阅时才会创建observable, 而只有在创建时 ,defer才会取用数据,这也保证了它的状态数据都是最新的。
见例子:
a = 10;
Observable<String> o1 = Observable.just("just result: " + a);
Observable<String> o2 =
Observable.defer(new Func0<Observable<String>>() {
@Override
public Observable<String> call() {
return Observable.just("defer result: " + a);
}
});
a = 12;
o1.subscribe(new Action1<String>() {
@Override
public void call(String t) {
System.out.println(t);
}
});
o2.subscribe(new Action1<String>() {
@Override
public void call(String t) {
System.out.println(t);
}
});
输出为:
"just result: 10"
"defer result: 12"
Map,FlatMap ——变换
根据应用场景来更容易消化知识,这次我们来到校园,有这么些学生。
Student s1 = new Student(110, "王小虎", 15, new ArrayList<Course>() {
{
add(new Course("物理"));
add(new Course("化学"));
}
});
Student s2 = new Student(111, "李刚", 17, new ArrayList<Course>() {
{
add(new Course("政治"));
add(new Course("语文"));
}
});
Student s3 = new Student(112, "李文龙", 16, new ArrayList<Course>() {
{
add(new Course("美术"));
add(new Course("武术"));
}
});
故事场景1——Map
需要通过遍历每个学生找到各自的班主任老师,并打印出老师的名字来。
/**
* 为每个学生来找到他们的老师并打印出名字来 Map
*/
Observable.just(s1, s2, s3).map(new Func1<Student, Teacher>() {
@Override
public Teacher call(Student student) {
Utils.p(student.name + "的老师是:");
return findTeacherBy(student);
}
}).subscribe(new Subscriber<Teacher>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable arg0) {
}
@Override
public void onNext(Teacher teacher) {
Utils.p(teacher.name);
}
});
public static Teacher findTeacherBy(Student student) {
Teacher teacher = null;
switch (student.id) {
case 110:
teacher = new Teacher("李老师");
break;
case 111:
teacher = new Teacher("张老师");
break;
case 112:
teacher = new Teacher("曹老师");
break;
default:
break;
}
return teacher;
}
打印输出为:
王小虎的老师是:
李老师
李刚的老师是:
张老师
李文龙的老师是:
曹老师
故事场景2——FlatMap
需要拿到每个学生他所学习的课程,并打印出课程名称来。
有两种方式来实现。
// 方案1:拿到每个学生后,遍历该学生的课程列表并打印
Observable.just(s1, s2, s3).subscribe(new Action1<Student>() {
@Override
public void call(Student arg0) {
for (Course course : arg0.courses) {
Utils.p(arg0.name + " " + course.courseName);
}
}
});
// 方案2:使用flatMap,不用自己遍历
Observable<Student> studentObservable = Observable.just(s1, s2, s3);
Observable<Course> courseObservable = studentObservable.flatMap(new Func1<Student, Observable<Course>>() {
@Override
public Observable<Course> call(Student arg0) {
Utils.p(arg0.name);
return Observable.from(arg0.courses);
}
});
courseObservable.subscribe(new Subscriber<Course>() {
@Override
public void onCompleted() {
Utils.p("发射结束");
}
@Override
public void onError(Throwable arg0) {
}
@Override
public void onNext(Course arg0) {
Utils.p(" " + arg0.courseName);
}
});
结果输出为:
王小虎
物理
化学
李刚
政治
语文
李文龙
美术
武术
发射结束
Map vs FlatMap
- Map输入到输出是 1v1的, 而FlatMap的输入到输出则是1vN的,所以你也能理解到为什么叫做flatMap了,flat 是扩展的意思。