RxJava学习笔记2介绍了在RxJava中如何指定事件发生线程以及事件消费线程,只需要简单调用
subscribeOn(XXXX) //发生线程
observeOn(XXX) //指定消费线程
这一篇我来学习一下RxJava中的核心原理 >>>>变换
就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列
->看不懂没关系 我看都不看!!!!!
map( ) 和 flatMap( ) 变换
/******** map()变换 ********/
Observable.just("images/logo.png") // 输入类型 String
.map(new Func1<String, Bitmap>() {
public Bitmap call(String filePath) { // 参数类型 String
return getBitmapFromPath(filePath); // 返回类型 Bitmap
}
})
.subscribe(new Action1<Bitmap>() {
public void call(Bitmap bitmap) { // 参数类型 Bitmap
showBitmap(bitmap);
}
});
//这个看起来很好理解吧 传入一个String类型的图片地址,在消费事件中拿到的是一个Bitmap图片
//Func1 -> 和我们之前写的非完整定义的Action0,1,2一样
/** new Func1(T1 , T2) 第一个参数是表示传入参数的数据类型 第二个参数 是返回结果的参数数据类型***/
//FuncX 和 ActionX 的区别在 FuncX 包装的是有返回值的方法。
以上的变化可以说是很好理解,下面再来看一个场景:
//假设有一个数据结构学生,现在需要打印出一组学生的名字。实现方式很简单:
Student[] students = ...;
Subscriber<String> subscriber = new Subscriber<String>() {
public void onNext(String name) {
Log.d(tag, name);
}
};
Observable.from(students)
.map(new Func1<Student, String>() {
public String call(Student student) {
return student.getName();
}
})
.subscribe(subscriber);
//map就是这么好用,如果要我们去打印学生选的课程,注意 课程也不是一个简单的数据哦,也是一个比较复合的数据接口,我们聪明的读者肯定想到了把我们传递的名字换成课程这个结构,在消费事件里面去一一解析即可,对,完全可以,但是我们为了体验一下FlatMap(),我们强制规定只能传入一个个解析好的课程名字给消费线程,我一句话打印就行,这样以来Map肯定不好使,因为Map是针对于 1 -> 1 ,但是 我们要的是 1 ->n(n>1)
我们直接看下一段代码
Student[] students = ...;
Subscriber<Course> subscriber = new Subscriber<Course>() {
public void onNext(Course course) {
Log.d(tag, course.getName());
}
};
Observable.from(students)
.flatMap(new Func1<Student, Observable<Course>>() { //传入一个Student >>返回一个被观察者 Course
public Observable<Course> call(Student student) {
return Observable.from(student.getCourses());
}
})
.subscribe(subscriber);
//我们发现 本来是我么创建一个Obserable 但是在内部 又创建了一个新的Obserable返回出来 嵌套 >>
//1. 使用传入的事件对象创建一个 Observable 对象;
//就是我们最原始的数据 携带 Student信息的Observable
//2. 并不发送这个 Observable, 而是将它激活,于是它开始发送事件;
//利用 每一个 Student获取到的相应的课程信息 Course而创建的Obserable
//-> 第一级的Obserable发送 事件 就是 每次都发送一个Student给 第二级 事件 处理 第一级的发送事件 是拿到解析出来的相应Course 一个个发送给打印订阅者
//3. 每一个创建出来的 Observable 发送的事件,都被汇入同一个 Observable ,
//而这个 Observable 负责将这些事件统一交给 Subscriber 的回调方法。
//这三个步骤,把事件拆成了两级,通过一组新创建的 Observable 将初始的对象铺平之后通过同一天链分发了下去。而这个铺平就是flatMap()的完成的操作。
//其实这很好理解 >>> 流水线型
类似于 组装的逆向过程 一辆车 >>>拆下车轮 >>>各种单体材料
肯定是在一个流水线上的 >>>车 >>>4个轮子 >>>一个轮子 好多螺丝 (好像有点牵强,但是就是这个理)
RxJava的所有变换其实都是利用 lift(Operator )来完成的
// lift()核心代码。
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
return Observable.create(new OnSubscribe<R>() {
public void call(Subscriber subscriber) {
Subscriber newSubscriber = operator.call(subscriber);
newSubscriber.onStart();
onSubscribe.call(newSubscriber);
}
});
}
//在 Observable 执行了 lift(Operator) 方法之后,会返回一个新的 Observable,
//这个新的 Observable 会像一个代理一样,负责接收原始的 Observable 发出的事件,并在处理后发送给 Subscriber。
//类似一种代理机制,通过事件拦截和处理实现事件序列的变换。
![这里写图片描述](http://img.blog.csdn.net/20160316113248554)
lift的使用示例
//下面这是一个将事件中的 Integer 对象转换成 String 的例子,仅供参考:
observable.lift(new Observable.Operator<String, Integer>() {
public Subscriber<? super Integer> call(final Subscriber<? super String> subscriber) {
// 将事件序列中的 Integer 对象转换为 String 对象
return new Subscriber<Integer>() {
public void onNext(Integer integer) {
subscriber.onNext("" + integer);
}
public void onCompleted() {
subscriber.onCompleted();
}
public void onError(Throwable e) {
subscriber.onError(e);
}
};
}
});
//**然而不管你是否理解了 lift() 的原理,RxJava 都不建议开发者自定义 Operator 来直接使用 lift(),而是建议尽量使用已有的 lift() 包装方法(如 map() flatMap() 等)进行组合来实现需求,因为直接使用 lift() 非常容易发生一些难以发现的错误。**
compose: 对 Observable 整体的变换 RxJava的另一个变换
lift() 是针对事件项和事件序列的,而 compose() 是针对 Observable 自身进行变换
假设在程序中有多个 Observable ,并且他们都需要应用一组相同的 lift() 变换。你可以这么写:
observable1
.lift1()
.lift2()
.lift3()
.subscribe(subscriber1);
observable2
.lift1()
.lift2()
.lift3()
.subscribe(subscriber2);
observable3
.lift1()
.lift2()
.lift3()
.subscribe(subscriber3);
升级一下>>>>>>
private Observable liftAll(Observable observable) {
return observable
.lift1()
.lift2()
.lift3()
}
liftAll(observable1).subscribe(subscriber1);
liftAll(observable2).subscribe(subscriber2);
liftAll(observable3).subscribe(subscriber3);
//可是 Observable 被一个方法包起来,这种方式对于 Observale 的灵活性似乎还是增添了那么点限制。怎么办?这个时候,就应该用 compose() 来解决了:
public class LiftAllTransformer implements Observable.Transformer<Integer, String> {
@Override
public Observable<String> call(Observable<Integer> observable) {
return observable
.lift1()
.lift2()
.lift3()
}
}
Transformer liftAll = new LiftAllTransformer();
observable1.compose(liftAll).subscribe(subscriber1);
observable2.compose(liftAll).subscribe(subscriber2);
observable3.compose(liftAll).subscribe(subscriber3);
//使用 compose() 方法,Observable 可以利用传入的 Transformer 对象的 call 方法直接对自身进行处理,也就不必被包在方法的里面了。