RxJava是一种响应式编程(个人理解),他有两个重要元素Observable(被观察者,事件源)和Subscriber(观察者)。Observable发出一个事件,Subscriber处理这个事件。
1.我们可以通过Observable的create方法来创建一个Observable对象。
Observable mObservable = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
subscriber.onNext("hello rxjava!");
}
});
注意create的参数,是一个OnSubscribe的实现类对象,OnSubscribe是Observable类中的内部接口。call方法中发出了一个“hello rxjava!”字符串。
2.创建一个Subscriber的实现类对象
Subscriber mSubscriber = new Subscriber() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
System.out.println(s);
}
};
实现onCompleted、onError、onNext三个方法,分别代表流程结束,出错,和数据处理。
3.通过subscribe方法完成事件源与观察者之间的订阅
mObservable.subscribe(mSubscriber);
完成订阅后,即会调用mSubscriber的onNext方法,打印出hello rxjava!
代码可进一步简化为:
Observable
.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
subscriber.onNext("hello rxjava!");
}
})
.subscribe(new Action1() {
@Override
public void call(String string) {
System.out.println(string);
}
});
subscribe参数除了Subscriber之外,还可以如下:
mObserable.subscribe(Action1, Action1, Action1);
参数中的三个Action1分别代表subscriber的onComplete,onError,onNext,此处我们只用到了onNext,因此代码可以简化为:
Observable
.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
subscriber.onNext("hello rxjava!");
}
})
.subscribe(new Action1() {
@Override
public void call(String string) {
System.out.println(string);
}
});
丰富的操作符是RxJava很正的强大之处,其可以对整个流程进行很好的控制。下面列出一些常用的操作符
其实上面的代码还可以继续简化:我们不仅可以通过create来创建一个Observable对象,还能通过just来创建。
如:
Observable
.just("hello rxjava!")
.subscribe(new Action1() {
@Override
public void call(String string) {
System.out.println(string);
}
});
just方法通过传入的value来返回一个相应的Observable对象
from接收一个集合参数,并将集合中的元素依次发出
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
list.add("g");
Observable
.from(list)
.subscribe(new Action1<String>() {
@Override
public void call(String string) {
System.out.println(string);
}
});
程序会将list中的元素一个一个的发送给subscriber,subscriber负责将他们打印出来。
from与just的区别:同样传入一个集合list,对于just,subscriber收到的也会是一个list;而对于from,subscriber收到的是list中的item
上面的例子,提供的原始数据是hello rxjava!,那么如何在subscriber中打印出hello rxjava!_eric。最先想到的方法:
Observable
.just("hello rxjava!")
.subscribe(new Action1() {
@Override
public void call(String string) {
System.out.println(string + "_eric");
}
});
当然这样是可行的,但是subscriber作为观察者,他的作用是对接收到的数据做最直接的处理,不希望对数据进行转换。此时map出现了,map的作用是对observable发出的数据进行转换,将转换后的数据重新发出,转换后的数据可以与原始数据一致,当然也可以不一致!
Observable
.just("hello rxjava!")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s + "_eric";
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String string) {
System.out.println(string);
}
});
这里map中对原始数据进行了处理。我们也可以增加多个map对数据进行一连串的变换。
Observable
.just("hello rxjava!")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s + "_eric";
}
})
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return s.hashCode();
}
})
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer hashCode) {
System.out.println(hashCode);
}
});
此代码将hello rxjava! >hello rxjava!_eric>hashCode值,Subscriber中接收到hashCode并打印出来。
接收一个observable的数据输出作为输入,转换为一个observable向下传递。
与map的区别:
1.map将接收到的数据处理后,转换为另一个数据传递下去
flatMap将接收到的消息转换为一个observable传递下去
2.如果map将消息处理为observable
类型,那么subscriber中的call方法的输入也将是observable
类型
而flatMap传递下去后,subscriber中输入的是observable所包含的类型T,而不是observable类型
也就是说,flatMap是将事件转化后返回一个Observable对象,但是这个对象并不是直接发送到Subscriber的回调方法中。他的原理是这样的:1.将数据转化为Observable对象。2.并不发送这个Obserable,而是将他激活,于是他开始发送事件。3.所有转为为的Observable发送的事件,全部交给同一个Observable,这个Observable负责将这些事件统一交给subscriber的回调方法。
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add(null);
list.add("c");
list.add("d");
list.add("e");
list.add("f");
list.add("g");
Observable
.just(list)
.flatMap(new Func1<ArrayList<String>, Observable<String>>() {
@Override
public Observable<String> call(ArrayList<String> strings) {
return Observable.from(strings);
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println(s);
}
});
过滤掉不符合条件的消息
指定消息数量
允许在处理观察者接收到消息前做一些事情, 比如将数据保存数据库等
Observable
.just(list)
.flatMap(new Func1<ArrayList<String>, Observable<String>>() {
@Override
public Observable<String> call(ArrayList<String> list) {
return Observable.from(list);
}
})
.filter(new Func1<String, Boolean>() {
@Override
public Boolean call(String s) {
return s != null;
}
})
.take(3) // 最多返回3个结果,应注意此处与filter的先后关系:如果filter放在take前面,则是成功filter过后的3个;
// 如果filter放在take后面,则是先取出3个再判断满不满足条件,如果不满足条件也不再增加
.doOnNext(new Action1<String>() {
@Override
public void call(String s) {
System.out.println("you can do something else about " + s);
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String o) {
System.out.println(o);
}
});
要注意filter和take的位置不同造成的不同结果。如上面代码:
如果filter放在take前面,则是成功filter过后的3个;
如果filter放在take后面,则是先取出3个再判断满不满足条件,如果不满足条件也不再增加
允许在一个事件触发后的一段时间内丢弃新的事件。常用作去抖动过滤。例如
throttleFirst(500, TimeUnit.MILLISECONDS)表示丢弃掉事件处理后500ms内的事件
一般情况下我们在回调中处理异常,这不仅要求每个回调都必须知道异常如何处理,导致重复代码,而且增加了代码之间的耦合性。
RxJava在整个消息传递的过程中,任意一个环节出现错误,就会跳过当前和后续的操作符,直接调用观察者的onError方法,操作符中不需要对错误进行处理;流程处理结束后会调用onComplete方法。因此,onComplete和onError是一定会被调用其一的。这大大简化了异常处理的方式。
现在的Android程序基本都离不开网络访问,另外开线程又是一件比较麻烦的事。
RxJava可以通过调度器来指定当前observable运行在哪个线程。
Observable
.just("www.baidu.com")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return getHttpResponse(s);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
textview.setText(s);
}
});
使用observeOn()和subscribeOn()来指定线程。
subscribeOn:事件产生的线程
observeOn:事件消费的线程
上面代码可以看到,网络请求时是放在Schedulers.io()线程中,更新UI是放在main线程。RxJava定义了几种线程分类:
这种在 subscribe() 之前写上两句 subscribeOn(Scheduler.io()) 和 observeOn(AndroidSchedulers.mainThread()) 的使用方式非常常见,它适用于多数的 『后台线程取数据,主线程显示』的程序策略。
浅析:(摘自http://gank.io/post/560e15be2dca930e00da1083)
subscribeOn和observeOn都进行了线程切换,不同的是,subscribeOn切换是在onSubscribe中,即在通知上一级OnSuscribe时,这时事件还没有发出,因此subscribeOn可以从事件发出的开端就造成影响。observeOn发生在他内建的subscriber中,即发生在给下一级subscriber发送事件时,因此observeOn控制的是他后面的线程。
subscribeOn和observeOn的混合调度:(详细解读可查看http://gank.io/post/560e15be2dca930e00da1083)