在看本文之前,假如你已经看过一些Rxjava的介绍,有了大致了解,但是仍然看不懂RxJava代码,并且对它的使用场景心存疑惑,那么本篇文章是适合你的。
RxJava的学习还是有一定门槛的,难度在于理解它的思维方式,和各种操作符的用处。本篇文章从最基础的RxJava示例来讲解,说明RxJava的基本使用及基础操作符的作用。
注:本篇文章的RxJava,指的是RxJava1,其他版本的操作符和用法可能会有一些变化。
本篇目录
- 前言:RxJava的一些介绍
- 得到Observable被观察者对象
- 得到Observer观察者对象
- 实现观察订阅
- RxJava实例讲解
- Retrofit+RxJava用法示例
前言:RxJava的一些介绍
首先要了解,RxJava是基于观察者模式的,简而言之就是观察者订阅了被观察者,然后被观察者产生的数据变化会通知到观察者,观察者从而作出反应。这里就不多做讲解了。在Android里,观察者模式的场景非常多,比如OnClickListener,比如EventBus等。
那么RxJava能干嘛呢?对入门来说,只要是“拿数据,做处理”这样的流程,都可以用RxJava实现。比如Retrofit网络请求经常搭配RxJava来实现。甚至打印一个字符串列表也可以用RxJava实现,只要你不嫌它大材小用。
在RxJava里,观察者用Observer类或者Subscriber类表示,其中后者是前者的实现类,两者用法基本相同。观察者就是处理数据的角色。
而被观察者用Observable类表示,它是产生数据的角色。
一、首先我们来看下如何得到一个Observable对象,也就是被观察者。
得到Observable有下面几种常用方法:
1.Observable.create(xxx)
这里的xxx为Observable.OnSubscribe对象,即订阅事件发生的时候,用于产生数据的对象。
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("1.....");
subscriber.onNext("2.....");
subscriber.onNext("3.....");
subscriber.onCompleted();
}
});
这个数据源产生的数据,就是三个字符串。
2.Observable.from(yyy)
这里的yyy为数组,集合,或者Future对象
List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("444444444");
Observable observable = Observable.from(list);
同样,这个observable对象所能产生的数据也是四个字符串。
3.Observable.just(x,y,z…)
这里的x,y,z…可以是不同类型的数据。
Observable observable = Observable.just(1,2,3,4,5);
上例这个observable能产生1~5的数字。
二、再来看下如何得到一个观察者对象(Subscriber或者Observer)
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
Log.d("test", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("test", "onError");
}
@Override
public void onNext(String s) {
Log.d("test", "onNext:"+s);
}
};
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
Log.d("test", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("test", "onError");
}
@Override
public void onNext(String s) {
Log.d("test", "onNext:"+s);
}
};
上面实现了两种观察者对象,Subscriber和Observer对象所要实现的抽象方法是一样的。
这里我们定义此观察者处理的数据类型为String类型。实际可根据需求来。按上面这样得到的观察者对象,能做什么呢?
onNext(String s):用于处理数据。
onCompleted():数据全部处理完成,会走到这里。
onError(Throwable e):数据处理过程出错,会走这里。
三、实现订阅
上面两步已经得到了被观察者和观察者对象,还差一步,就是确立订阅关系:
observable.subscribe(observer);
或者
observable.subscribe(subscriber);
看上面这两行代码会发现,在RxJava里,订阅关系是被观察者(observable)订阅了观察者(observer),与我们平时的理解相反。
其实Rxjava这么写只是为了链式调用比较方便。真正subscribe()方法的源码实现里,仍然是观察者订阅了被观察者。
实际使用中,还可以通过observable.subscribe(new Action0(){…})这样的方式,即不必定义观察者,而是通过Action0这样的类包装得到。下面会有例子。
四、实例解析
把上面三步用链式调用连接起来,完整的例子如下:
例1:打印字符串基本示例
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("str1");
subscriber.onNext("str2");
subscriber.onNext("str3");
subscriber.onCompleted();
}
}).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
Log.d("test", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("test", "onError");
}
@Override
public void onNext(String s) {
Log.d("test", "onNext:"+s);
}
});
运行结果:
D/test: onNext:str1
D/test: onNext:str2
D/test: onNext:str3
D/test: onCompleted
这个例子实现的功能很简单,就是依次打印三个字符串,完成后再打印"onCompleted"。如果流程中出了错误,则会打印"onError"。
例2:流程前后加入额外处理的示例
subscribe()方法传入的可以是Subscriber对象,Observer对象,或者Action1对象。
List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("44444");
Observable.from(list)
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("test", "call:"+s);
}
});
同样功能很简单,就是依次打印四个字符串。
如果想在打印前后做一些额外处理,怎么办呢?可以像下面这样改:
List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("44444");
Observable.from(list)
//处理前的操作
.doOnSubscribe(new Action0() {
@Override
public void call() {
Log.d("test", "doOnSubscribe");
}
})
//处理完成后的操作
.doOnCompleted(new Action0() {
@Override
public void call() {
Log.d("test", "doOnCompleted");
}
})
//正式处理的操作
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("test", "call:"+s);
}
});
上面加上了doOnSubscribe和doOnCompleted操作,用于在正式处理前后进行额外处理。
类似地,在流程发生错误,或者终止等时机,RxJava都有对应的方法用于处理。
还可以看到,上面出现了Action0和Action1两个类,它们有什么区别呢?
Action0的call()不会传入参数,而Action1的call()会传入一个参数。类似地还有Action2,Action3,Action4等等。
运行结果:
D/test: doOnSubscribe
D/test: call:11111
D/test: call:22222
D/test: call:33333
D/test: call:44444
D/test: doOnCompleted
例3:数据处理前的筛选变换
Observable.just(1,2,3,4,5)
.filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer%2==0;
}
})
.subscribe(integer -> Log.d("test", "call:"+integer));
这里有个操作符filter,顾名思义是用来筛选数据的。而Func1这个类,用于实现具体的处理逻辑,它和Action1这个类的不同点在于有返回值。
这个例子的功能是筛选出能被2整除的数字,运行结果如下:
D/test: call:2
D/test: call:4
再看一个常用操作符,map:
Observable.just(1,2,3,4,5)
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
return integer*2;
}
})
.subscribe(integer -> Log.d("test", "call:"+integer));
map操作符的作用是对数据进行统一的处理。在本例中是对各个数字乘以2。
运行结果如下:
D/test: call:2
D/test: call:4
D/test: call:6
D/test: call:8
D/test: call:10
还有其它各种处理数据的操作符,如得到数据的前几位,后几位,排序等。你能想到的各种常用处理,RxJava基本都有对应的操作符。
另外这个例子中使用了lambda表达式,简化了代码。
例4:线程的切换示例
使用RxJava可以很方便地进行线程切换,每一步操作都可以切换线程。如下例:
Observable.just(1, 2, 3, 4) // IO 线程,由第一个 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新线程,由上一行的 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 线程,由由上一行的 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主线程,由由上一行的 observeOn() 指定
切换线程可以使用subscribeOn和observeOn两个操作符。这两个有什么区别呢?
subscribeOn传入的的是被观察者,即数据源产生数据时所在的线程。
observeOn传入的是处理数据所在的线程。
如果链式调用中,出现了多个subscribeOn,则数据源产生数据的线程是首个subscribeOn指定的线程。
而每调一次observeOn传入不同的线程,下一步的数据操作就会变到该线程里。
可参考扔物线的RxJava讲解。
五、最后,贴上Retrofit+RxJava使用示例:
service.login(phone, password)//获取Observable对象
.subscribeOn(Schedulers.newThread())// 定义登录操作(获取Observable对象)在新的线程进行
.observeOn(Schedulers.io())//请求完成后在io线程中执行保存用户信息
.doOnNext(new Action1<UserInfo>() {
@Override
public void call(UserInfo userInfo) {
saveUserInfo(userInfo);//保存用户信息到数据库
}
})
.observeOn(AndroidSchedulers.mainThread())//最后在主线程中执行
.subscribe(new Subscriber<UserInfo>() {
@Override
public void onCompleted() {
//操作完成
}
@Override
public void onError(Throwable e) {
//请求失败
}
@Override
public void onNext(UserInfo userInfo) {
//请求成功,显示用户信息,在主线程
showUserInfo();
}
});