引入
响应式编程就是与异步数据流交互的编程范式。
事件总线(Event Buses)或一些典型的点击事件本质上就是一个异步事件流(asynchronous event stream),这样你就可以观察它的变化并使其做出一些反应(do some side effects)。最重要的是,你会拥有一些令人惊艳的函数去结合、创建和过滤任何一组数据流。 这就是”函数式编程”的魔力所在。一个数据流是一个按时间排序的即将发生的事件(Ongoing events ordered in time)的序列。如下图,它可以发出3种不同的事件(上一句已经把它们叫做事件):一个某种类型的值事件,一个错误事件和一个完成事件。
为了展示响应式编程真正的魅力,我们假设你有一个”双击”事件流,为了让它更有趣,我们假设这个事件流同时处理”三次点击”或者”多次点击”事件,然后深吸一口气想想如何用传统的命令式和状态式的方式来处理,我敢打赌,这么做会相当的讨厌,其中还要涉及到一些变量来保存状态,并且还得做一些时间间隔的调整。而用响应式编程的方式处理会非常的简洁,实际上,逻辑处理部分只需要四行代码。
图中,灰色盒子表示将上面的事件流转换下面的事件流的函数过程。
基础
RxJava最核心的两个东西是Observables(被观察者,事件源)和Subscribers(观察者)。一个Observable可以发出零个或者多个事件,知道结束或者出错。每发出一个事件,就会调用它的Subscriber(观察者|订阅者)的onNext方法,最后调用Subscriber.onNext()或者Subscriber.onError()结束。与观察者模式明显的不同时:如果一个Observerble没有任何的的Subscriber,那么这个Observable是不会发出任何事件的。
Observable.just就是用来创建只发出一个事件就结束的Observable对象
Observable myObservable = Observable.just(“Hello, world!”);
我们只需要在onNext的时候做一些处理,这时候就可以使用Action1类。
Action1<String> onNextAction = new Action1<String>() {
@Override
public void call(String s) {
System.out.println(s);
}
};
当然,subscribe方法有一个重载版本,接受三个Action1类型的参数,分别对应OnNext,OnComplete, OnError函数。
上面代码最终合并结果:
Observable.just("Hello, world!")
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println(s);
}
});
变换
新需求,比如我想在hello world中加上我的签名,你可能会想到去解决方案:
1.修改Observable对象:
Observable.just("Hello, world! -Dan")
.subscribe(s -> System.out.println(s));
2.修改Subscribe
Observable.just("Hello, world!")
.subscribe(s -> System.out.println(s + " -Dan"));
更好地实现方案,借助操作符,用于在Observable和最终的Subscriber之间修改Observable发出的事件。解决对Observable对象的变换的问题。
操作符(Operators)
1.map操作符
Observable.just("Hello, world!")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s + " -Dan";
//此处的 s即为发送事件流“Hello, world!”
}
})
.subscribe(s -> System.out.println(s));
map()操作符就是用于变换Observable对象的,map操作符返回一个Observable对象,这样就可以实现链式调用.
**进阶:**map操作符可以改变事件类型,比如我们把初始字符串转换成Integer
Observable.just("Hello, world!")
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return s.hashCode();
}
})
.subscribe(i -> System.out.println(Integer.toString(i)));
当然可以包含多个map针对同一事件流转换不同的类型,下一次转换是在上一次转换完成的事件流基础上做的转换。例如下面代码(用rx2)最终输出结果为:
E/rx—->: hello wordmap第一次转换map第二次转换’
Observable.just("hello word")
//注意此处的参数,第一个为接受参数泛型,第二个为装换后参数
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String s) throws Exception {
return s+"map第一次转换";
}
})
.map(new Function<String, String>() {
@Override
public String apply(@NonNull String integer) throws Exception {
return integer+"map第二次转换";
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
Log.e("rx---->", s);
}
});
参考:
1.http://www.devtf.cn/?p=174
2.https://github.com/lzyzsd/Awesome-RxJava