您的位置:首页 > 编程语言 > Java开发

RxJava介绍和使用

2016-04-20 17:19 387 查看
最近开始研究RxJava,真坑爹,这个东西不好搞,可能本人的智商堪忧!终于上手了,自己总结一下。

RxJava 最早是后端用的,但是RxJava在后端上倒是不太流行,反而在Android上流行起来了!Android中UI开发需要异步操作,使用RxJava可以随意切换线程,用起来比较方便,代码比较清晰。

RxJava 类似 观察者模式。有一个Observable(被观察者,事件的发起者)和一个观察者(Subscriber,事件的接收者)。Observable发出一系列的事件,然后Subscriber处理这些事件。

Observable 可以发送零到多个事件;Subscriber会接收它发的每一个事件。如果Observable没有对应的Subscriber,不会发送任何事件。

如何发送数据

首先我们看一下Observable 是如何创建和发送事件的。

我们需要一个Observable,用来发送事件。我们可以通过
create()
方法来创建一个Observable。它决定什么时候触发事件以及怎么发送事件。在
create()
里传入了一个
OnSubscribe
,它会有一个
call
方法,它提供了一个
Subscriber
来通过
onNext
发送事件。发送完毕之后
Subscriber
会提供一个
onComplete
方法,来结束事件的发送。

Observable<String> mObservable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
LogUtils.e("开始发送事件");
subscriber.onNext("Hello World");//通过onNext 发送事件
subscriber.onCompleted();//结束发送事件
}
});


然后我还需要一个
Subscribe
用来接收接收
Observable
发送的事件。

Subscriber<String> mSubscriber = new Subscriber<String>() {
//在监听事件发送刚开始也就是subscribe()刚开始,而事件还未发送之前被调用,可以用于做初始化工作
@Override
public void onStart() {
super.onStart();
LogUtils.e("开始接收数据");
}

@Override
public void onCompleted() {
LogUtils.e("接收事件结束");
}
@Override
public void onError(Throwable throwable) {
LogUtils.e("接收事件发生错误:" + throwable.getMessage());
}
//对应Observable中的onNext对应,Observable中的onNext调用一次,这里对应也会调用一次
@Override
public void onNext(String s) {
Toast.makeText(MainActivity.this, "" + s, Toast.LENGTH_SHORT).show();
LogUtils.e(s);
}
};


3.前面说,如果Observable没有对应的Subscriber,不会发送任何事件。所以我们还需要
Subscriber
Observable
的订阅。

mObservable.subscribe(mSubscriber);


这样就完成了事件的发送于接收。

创建Observable的方式

在RxJava中创建
Observable
还有其它的方式

如果传递的数据是多个同类型的数据,可以使用以下的方式:

//已发送 “Hello”,”World”,”RxJava”,相当于调用三次onNext,并调用onComplete

Observable observable = Observable.just(“Hello”, “World”,”RxJava”);

如果传递的数据是数组:

String[] strArr = {"Hello", "World","RxJava"};
Observable observable = Observable.from(strArr);


如果传递的数据是集合:

List<String> strList = new ArrayList<>();
strList.add("Hello");
strList.add("World");
strList.add("RxJava");
Observable observable = Observable.from(strList);


常用的操作符

map

map()在RxJava里非常常用,它可以对事件进行变换。非常喜欢这个操作符,它可以将事件序列中的对象或整个发送的整个序列进行变换,进行不同的处理。例如:我们想需要传递一个图片的Bitmap集合,但是我们只有一个图片的URL集合。我们就可以使用map对URL集合进行处理。

List<String> strList = new ArrayList<>();
strList.add("http://h.hiphotos.baidu.com/zhidao/pic/item/3812b31bb051f81991b9d8dbdcb44aed2f73e787.jpg");
strList.add("http://cdn.duitang.com/uploads/item/201412/19/20141219154459_3P4G2.jpeg");
strList.add("http://ww1.sinaimg.cn/crop.7.22.1192.1192.1024/5c6defebjw8epti0r9noaj20xc0y1n0x.jpg");
Observable observable = Observable.from(strList)
//map的参数是一个Func1类,它的第一个泛型是指传递数据类型,第二个参数是经过转换过返回的数据类型
//这里我们转换之前的数据类型是String,处理后返回的是Bitmap
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String s) {
Bitmap bitmap = parseString2Bitmap(s);
return bitmap;
}
});


flatMap

flatMap的功能比较难解释,我们先举个例子啊;假如我们有若干个用户买了我们若干的产品,我们想知道哪些产品比较受欢迎,需要我们打印一下这些用户购买的产品。我们这里只打印产品的名称。

我们先准备一下数据:

List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
user.id = i;
user.name = "UserName = " + i;
user.address = "火星" + i + "号";
for (int j = 0; j < 5; j++) {
Product product = new Product();
product.name = "ProductName" + j;
product.price = j * j + "";
product.number = j * 1000 + "";
user.mProducts.add(product);
}
users.add(user);
}


接下来我们来过滤这些用户:

Observable observable = Observable.from(users)
//利用flatMap,将之前我们User集合的每个user中的Product集合提取出来构建一个新的Observable,然后再将product一次往下传递
.flatMap(new Func1<User, Observable<Product>>() {
@Override
public Observable<Product> call(User user) {
//我们在创建第一个Observable时使用User集合,我们把每个User提取出来,获取其中的Product集合,并利用Product集合创建一个新的Observable
return Observable.from(user.mProducts);
}
//通过上面的flatMap,使用Product集合创建新的Observable,我们在通过map将product的名称提取出来,并且传递到Subscribe
}).map(new Func1<Product, String>() {
@Override
public String call(Product p) {
return p.name;
}
})


这里我们通过
flatMap
map
的结合,避免了使用for循环,而是直接将每个用户名下的所有产品挨个传递出去,到Subscribe里处理。

线程的切换

subscribeOn
observeOn


RxJava还有个比较牛B的地方,就是可以对线程进行自由的变换。比如主/子线程的切换。

RxJava 提供了
subscribeOn
observeOn
来实现线程的切换。可以上事件的产生和处理分布在不同的线程。例如我们可以在子线程获取网络数据,在主线程显示这些数据。

默认情况下如果不指定线程,RxJava的所有操作都是在主线程里的,在Android开发中如果设计到网络等操作,是会报异常的,我们可以使用
subscribeOn
observeOn
来实现线程的切换,来处理类似的这些情况。

比如我们现在有一个是从服务器拉取数据的方法叫做
getNetData()
,它的返回值是String类型,我们都知道在Android中网络数据的访问是不能在主线程里进行的,我们只能在子线程里进行,然后通过
Handler
发送到主线程。这样做起来稍微麻烦一些,如果我们使用RxJava就会很简单。

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
//获取网络数据
String result = getNetData();
subscriber.onNext(result);
subscriber.onCompleted();
}
//使用subscribeOn(),指定发送事件所在的线程
}).subscribeOn(Schedulers.newThread())
//使用observeOn(),指定观察者接收事件所在的线程
.observeOn(AndroidSchedulers.mainThread());


然后我们根据上面,创建
Subscriber
,然后监听着
Observable
发送过来的数据就可以了。

本文参考 给 Android 开发者的 RxJava 详解,感谢扔物线大神
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android RxJava RxAndroid