RxJava学习笔记3

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 方法直接对自身进行处理,也就不必被包在方法的里面了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值