rxjava推出已经有相当长的一段时间了。本人作为使用rxjava的菜鸟想对一些相关的使用做一些备注和总结。由于本人写作能力有限,先推荐几篇比较优秀的文件
rxjava 到底是个什么东西。扔物线大神说的很好,“异步” 。
rxjava的目的和 Handler、AsyncTask一样都是为了实现线程间的切换。但是他比 handler、asynctask这些都要灵活。
Observable.subscribe(Observer)
看起来像是被观察者订阅了观察者。这是为了保持代码的链式结构。//第一步: 创建 Observable(被观察者)
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
System.out.println("+++++++++++++++++++++++++++++" + 1);
emitter.onNext(2);
System.out.println("+++++++++++++++++++++++++++++" + 2);
emitter.onNext(3);
System.out.println("+++++++++++++++++++++++++++++" + 3);
/* 这里如果有异常的话,一定是发生在 onComplete 之前,不然异常无法被捕获处理造成闪退 */
//String a = null;
//a.length();
//String[] b = {"1"};
//b[5].length();
//如果 onError 之前没有异常发生, 那么 onError 之后的代码将继续执行,但是不会被观察者捕获
emitter.onError(new Throwable("Throw an error !"));
//当我们已经抛出了一个异常那么第二个异常也无法被捕获处理造成闪退
//emitter.onError(new Throwable("Throw second error !"));
System.out.println("+++++++++++++++++++++++++++++" + "onError");
emitter.onComplete();
System.out.println("+++++++++++++++++++++++++++++" + "onComplete");
emitter.onNext(4);
System.out.println("+++++++++++++++++++++++++++++" + 4);
}
})
//第三步:建立订阅关系
.subscribe(new Observer<Integer>() {
//第二步:创建observer(观察者)
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG + "onSubscribe", d.isDisposed() + "");
}
@Override
public void onNext(Integer integer) {
Log.i(TAG + "onNext", integer + "");
if (integer == 3) {
//切换操作,观察者不再接受上游事件, 此后上游Observable将不能再抛出异常,否则异常无法被捕获处理。
disposable.dispose();
}
}
@Override
public void onError(Throwable e) {
Log.e(TAG + "onError", e.getMessage().toString());
}
@Override
public void onComplete() {
Log.e(TAG + "onComplete", "onComplete");
}
});
总结: 这里是一些注意点有点绕,初学者可以暂且跳过
a.lenght()
执行后将在observer中的onError方法中捕获 NullPointException 异常,并且这之后的代码将不再执行。emitter.onError
和 emitter.onComplete()
被调用后订阅关系消息源中的代码将继续执行,但观察者将不会对任何发出的消息进行处理。先看代码:
observable
//指定发射事件的线程为 io 线程
.subscribeOn(Schedulers.io())
//指定接收者线程为 Android主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer1);
此方法用于指定消息源发生的线程
此方法用于指定消息处理的线程
注意:
通过以上我们简单的了解了。rxjava的基本使用。但如果rxjava仅仅是这样的话是不能满足多样的使用场景的,那也太弱了。下面我们来看看rxjava那些灵活的使用。
create()
方法是Rxjava中创建事件序列的最基本的方法。除此之外,rxjava还提供了一下快捷创建事件序列的方法
just(T...)
/*
just(T...)方法将依次发射 1,2,3,4等事件,相当于 执行 onNext(1), onNext(2), onNext(3) onNext(4);
just方法最大的参数个数为 10。
*/
Observable.just(1, 2, 3, 4).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
//此处将依次收到 1,2,3,4等 4 个消息
System.out.println("justjustjustjustjustjustjust------" + integer);
}
});
fromArray
/*
fromArray 方法的效果和just,fromIterable一样,只是接收的参数是一个数组。
当然,fromArray(1, 2, 3, 4) 像这样调用也是一样的。
显然的fromArray方法的参数个数是没有限制的。
*/
Integer[] strings1 = {1, 2, 3, 4};
Observable.fromArray(strings1).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("fromArrayfromArrayfromArrayfromArray++++++++" + integer);
}
});
fromIterable extends T>
List<String> stringList = new ArrayList<>();
stringList.add("1");
stringList.add("2");
stringList.add("3");
stringList.add("4");
/*
fromIterable extends T> 将依次发射 1,2,3,4,等4个事件,效果和上面just方法类似,
但,很明显的fromIterable方法将能承载更多的数据
*/
Observable.fromIterable(stringList).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("fromfromfromfromfromfromfromfrom-------" + s);
}
});
如上例子中,如果我们不需要对 异常、完成 等信息进行处理,那么直接订阅一个consume
作为观察者即可。
当然rxjava也提供了不同参数个数的subscribe()
方法,可以根据需求设置捕获 异常 或 完成 等消息
为了方便使用,以及满足各种使用场景,rxjava提供了众多的方法,rxjava官方称之为“操作符”。当然上述Observable的各种创建方法也是操作符。下面我们来看一下常用的操作符。
Observable.just(1, 2, 3, 4)
.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
//将源消息中的integer 值转换成我们需要的 String值
return "The value is " + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("------------" + s);
}
});
map是一个比较简单的转换操作符,通过规则将源消息中的 值,转换成我们需要的值
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
.flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
String a = integer + "";
return Observable.just(a).delay(10, TimeUnit.SECONDS);
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("+++++++++++++++" + s);
}
});
如上代码,flatMap将integer类型的消息转换成了String类型的消息。这里要注意,flatMap是无序的。
当然flatMap有很多其他变体,(如可以可以出来异常、完成时间的flatMap(Function onNextMapper, Function onErrorMapper, Callable)
)等等。这里我只讲最基本的。
groupby将源Observable拆分成多个GroupedObservable,每个GroupedObservable发射一个Observable中的子序列。
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
.groupBy(new Function<Integer, Integer>() {
@Override
public Integer apply(Integer integer) throws Exception {
//根据原始消息的不同,将源Observable拆分成不同的GroupedObservable。
// 并给下游消息队列(即GroupedObservable)加上不同的 key 值
if (integer % 2 == 0) {
return 2;
} else {
return 1;
}
}
}).subscribe(new Consumer<GroupedObservable<Integer, Integer>>() {
@Override
public void accept(GroupedObservable<Integer, Integer> integerIntegerGroupedObservable) throws Exception {
//获取消息队列的 key之,采用 key 值来分辨消息队列的种类
int key = integerIntegerGroupedObservable.getKey();
switch (key) {
case 1:
integerIntegerGroupedObservable
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("---------------" + integer + " is a 奇数" );
}
});
break;
case 2:
integerIntegerGroupedObservable.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("+++++++++++++++" + integer + " is a 偶数" );
}
});
break;
default:
break;
}
}
});
这里有一个 groupby 的变种,groupBy(Function keySelector, Function valueSelector)
其中第二个参数是对消息的值进行的变换。
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
.scan(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer sum, Integer item) throws Exception {
//return值 将作为下次调用此函数的第一个参数值
//注意:这里会先将第一个消息发出给订阅者来处理。
// 然后再将第一个消息的值作为此函数的第一个参数,将第二个消息作为第二个参数来第一次执行这个函数
return sum + item;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("===========" + integer);
}
});
从代码运行结果看出,scan使得订阅者每次接收到的消息值都和上一次的消息值有关。*注意:*第一次的消息是不变的并会作为apply方法第一次执行的第一个参数。当然我们也可以改变scan返回的消息的数据类型,这时候就要调用scan(final R initialValue, BiFunction accumulator)
来设置观察者接收到的第一个消息的初始值 initialValue;
window 操作符合buffer操作符类似。但buffer是将消息源转换成一个个列表发射,而window是将消息源转换成多个Observable,每个Observable发射一个子集。
Observable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
.window(3)
.subscribe(new Consumer<Observable<Integer>>() {
@Override
public void accept(Observable<Integer> integerObservable) throws Exception {
System.out.println("==================" + "第" + time + "组");
time ++;
integerObservable.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("----------" + integer);
}
});
}
});