RxJava提供了响应式编码规范,而RxAndroid是专供Android平台的RxJava(只是针对平台增加了少量类),一般Android开发者口中的RxJava指的便是RxAndroid。关于响应式编程的概念这里不多说,网上一大堆,我就简单说明下响应式编程与传统编程的区别。如果逻辑B依赖于逻辑A,逻辑C依赖于逻辑B,那么:
- 传统编程中的作法是在A执行完成后去执行B,B执行完毕后执行C,除了A、B、C本身的逻辑外,这部分由依赖产生的先后执行逻辑也是由开发者编写。
- 响应式编程中,会先将A、B、C做个依赖绑定,A->B->C,就像水流一样,从A流到B,再从B流到C,依赖产生的先后执行逻辑由语言或者库提供支持,开发者只需要编写A、B、C本身的逻辑以及告诉提供方三者间的关系即可。换句话说,就是B会自动响应A的执行结果,C会自动响应B的执行结果。
响应式编程可以很优雅地处理任务间(或者业务间)的依赖关系,而这关系就像流一样,并且多用于异步场景,且由于大家熟知的响应式编程库RxJava的主要应用场景也是异步,主要应用手段是流,因此不少文章简单粗暴地将响应式编程等同是异步+流,这个是比较片面的。
示例
我们来看个具体的例子,加深下理解。本例中需要处理三个任务,分别为A、B、C,这三个任务都需要在工作线程中执行,A执行完以后延迟1S执行B,B执行完以后延迟1S执行C。
以下为公共代码,定义了A、B、C三个任务以及定时器:
public class TaskA implements Runnable {
@Override
public void run() {
// do something
}
}
public class TaskB implements Runnable {
@Override
public void run() {
// do something
}
}
public class TaskC implements Runnable {
@Override
public void run() {
// do something
}
}
public class Timer {
private static final Timer INSTANCE = new Timer();
private Handler mHandler;
private Timer() {
HandlerThread thread = new HandlerThread("timer");
thread.start();
mHandler = new Handler(thread.getLooper());
}
public static Timer get() {
return INSTANCE;
}
public void post(Runnable runnable) {
mHandler.post(runnable);
}
public void postDelayed(Runnable runnable, long delay) {
mHandler.postDelayed(runnable, delay);
}
}
传统编程
Timer.get().post(new Runnable() {
@Override
public void run() {
new TaskA().run();
Timer.get().postDelayed(new Runnable() {
@Override
public void run() {
new TaskB().run();
Timer.get().postDelayed(new Runnable() {
@Override
public void run() {
new TaskC().run();
}
}, 1000);
}
}, 1000);
}
});
传统编程方式的问题非常突出,嵌入层次太多,随着依赖关系的增多以及复杂化,这样的代码会变得极其臃肿且不易阅读和维护。
响应式编程
首先我们需要编写一个支持响应式编程规范的库,代码如下(这个类很多情况没有考虑到,仅仅是为了演示用):
public class StreamTimer implements Runnable {
private List<Task> mTasks = new LinkedList<>();
public StreamTimer() {
}
public StreamTimer next(Runnable runnable) {
return next(runnable, 0);
}
public StreamTimer next(Runnable runnable, long delay) {
Task task = new Task(runnable, delay);
mTasks.add(task);
return this;
}
public void startup() {
startNextTimer();
}
private void startNextTimer() {
if(mTasks.isEmpty()) {
return;
}
Task task = mTasks.get(0);
Timer.get().postDelayed(this, task.delay);
}
@Override
public void run() {
Task task = mTasks.remove(0);
task.runnable.run();
startNextTimer();
}
private class Task {
Runnable runnable;
long delay;
Task(Runnable runnable, long delay) {
this.runnable = runnable;
this.delay = delay;
}
}
}
执行A、B、C任务的代码如下:
new StreamTimer()
.next(new TaskA())
.next(new TaskB(), 1000)
.next(new TaskC(), 1000)
.startup();
next表示新增一个任务且需要在上一次任务执行完毕后才执行。以上代码非常简洁且可读性很强,任务间的依赖关系非常清晰,拓展也非常简单,新增任务时只需要在合适的地方插入next方法即可。