(1),什么是RxJava?
RxJava是 ReactiveX(ReactiveX推荐http://reactivex.io/) 在JVM上的一个实现,ReactiveX使用Observable序列组合异步和基于事件的程序。RxJava是在ReactiveX的一个延伸,RxJava是轻量级的,RxJava只关注Observable的抽象和与之相关的高级函数。通俗一点,RxJava是一个编程模型,提供一致的编程接口,帮助我们处理异步数据流。RxJava是以函数的响应方式体现。
(2),为什么要使用RxJava?
从表面来讲,RxJava编写代码简洁,注意简洁不是简单。代码量并不一定能减少,只是结构清晰,便于阅读。其实最根本的是,RxJava可以灵活的处理数据流或事件,高效的处理线程创建和并发。
(1),如果使用AndroidStudio,需要在gradle中添加
//RxJava的依赖包
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
//RxAndroid的依赖包
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
(2),这里以RxJava2.x版本介绍如何使用,建议读者可以先看下RxJava1.x版本,这样可以对比版本差异,有助于更好的理解RxJava。
(3),使用场景,通常在Android开发过程中,需要在后台线程处理一些任务。比如:AsyncTask,ContentProvider,Services,网络请求等。使用AsyncTask会导致内存泄漏,ContentProvider和Services配置繁琐。而RxJava就可以帮助我们解决这些问题。
(1),概念:Android开发中,我们经常用到的点击事件就是观察者模式。View就是被观察者,OnClickListener 是观察者,两者通过setOnClickListener建立绑定关系(这里简单介绍,如果想了解Android更多开发模式,推荐书籍《Android源码设计模式》)
(2),Observable(被观察者)/Flowable(被观察者 RxJava2.x版本新增),Observer(观察者)/Subscriber(观察者),Subscribe(订阅者)。观察者和被观察者通过订阅建立绑定关系。
(3),RxJava2.X中, Observeable用于订阅Observer ,是不支持背压的,而 Flowable用于订阅Subscriber ,是支持背压(Backpressure)的。背压是指:被观察者发送数据或事件的速度,远快于观察者的处理速度的情况下,一种告诉上游的被观察者降低发送速度的策略。关于背压的概念推荐http://blog.csdn.net/jdsjlzx/article/details/52717636
(1),create()
使用 Create操作符从头开始创建一个Observable/Flowable,这个操作符传递一个接受观察者作为参数的函数。
//创建被观察者
Observable observable = Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter e) throws Exception {
e.onNext("Hello Word");
e.onComplete();
}
});
//创建观察者
Observer observer = new Observer() {
//这是RxJava2.x新加入的方法,在订阅之后发送数据之前,而Disposable可用于取消订阅
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "onSubscribe");
}
@Override
public void onNext(String s) {
Log.e(TAG, s);
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError");
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete");
}
};
//建立绑定关系
observable.subscribe(observer);
以上代码为Observable 实现方式 , 打印结果为 onSubscribe->Hello Word->onComplete。在这里就可以看出,onSubscribe会在onNext之前调用,这里可以在onSubscribe方法中做一些初始化的操作。
Flowable flowable = Flowable.create(new FlowableOnSubscribe(){
@Override
public void subscribe(FlowableEmitter e) throws Exception {
e.onNext("Hello Word");
e.onComplete();
}
}, BackpressureStrategy.BUFFER);//背压模式,不指定不支持背压
Subscriber subscriber = new Subscriber() {
@Override
public void onSubscribe(Subscription s) {
Log.e(TAG, "onSubscribe");
s.request(1);//request(n)来告诉上游被观察者发送多少个数据
}
@Override
public void onNext(String s) {
Log.e(TAG, s);
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError");
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete");
}
};
flowable.subscribe(subscriber);
以上代码为Flowable 实现方式打印结果为onSubscribe->HelloWord->onComplete。这里需要注意,如果有初始化操作要在request(n)之前执行。Flowable是支持背压的,简单来说,上游被观察者会响应下游观察者的数据请求,下游观察者通过request(n)通知上游被观察者发送多少请求。这样避免被观察者发送数据或事件的速度,远快于观察者处理数据或事件的速度,造成大量数据或事件堆积。
被观察者ObservableEmitter/FlowableEmitter,这里指发射器的意思,可以发射onNext(),onError(),onComplete()。被观察者可以发送多个onNext(),观察者也可以接收多个onNext()。被观察者发送了onComplete()/onError()之后事件继续发送,而观察者接收到onComplete()之后不在继续接收事件。被观察者可以不发送onComplete()/onError(),两者必须是唯一并且互斥。
(2),just()
将一个或多个对象转换成发射这个或这些对象的一个Observable/Flowable
Observable.just("Hello World", "Very Good").subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.e(TAG, s);
}
});
Flowable.just("Hello World", "Very Good")
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) {
Log.e(TAG, s);
}
});
这里有个Consumer,表示观察者只关心onNext()事件,其他事件不管,因此可以这么写
(3),range()
创建一个发射指定范围的整数序列的Observable/Flowable,可以指定范围的起始和长度。接受两个参数,一个是范围的起始值,一个是范围的数据的数目。
Observable.range(3, 4).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e(TAG, integer + "");
}
});
//输出3,4,5,6
Flowable.range(2,4).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e(TAG, integer + "");
}
});
//输出2,3,4,5
(4),flatMap()
将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable。
如何使用flatMap(),例如:我们需要做一个商品分类,主商品(Goods)和子商品(Category)。
new Thread(new Runnable() {
@Override
public void run() {
//在子线程获取数据
List list=//数据源,所有商品,比如:鞋子类别中包含运动鞋,登山鞋,板鞋等
for(//主商品,如:鞋子){
Log.e(TAG,"主商品名称");
for(//子商品,如:运动鞋){
//主线程中更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e(TAG,"子商品");
}
});
}
}
}
}).start();
这段伪代码是我们常用的写法,在子线程中获取数据,主线程中更新UI,如果数据比较多,逻辑复杂代码可读性当然会差。再看看flatMap()应该怎么写
Flowable.fromIterable(goods).flatMap(new Function>() {
@Override
public Publisher apply(Goods goods) throws Exception {
return Flowable.fromIterable(goods.getList());
}
})
.subscribeOn(Schedulers.io())//下边会介绍
.observeOn(AndroidSchedulers.mainThread())//下边会介绍
.subscribe(new Consumer() {
@Override
public void accept(Category category) throws Exception {
Log.e(TAG, category.getName());
}
});
对比一下这种方式结构清晰了很多,和flatMap()一样的还有一个操作符contactMap(),唯一的区别就是flatMap()是无序的,最后输出的和原序列不一定相同。contactMap()是有序的,最后输出的和原序列相同
有关操作符就介绍到这里,如果想了解其他操作符可以进入http://reactivex.io/进行查看
(1),对于Android开发来说,这也是最有用的地方。我们经常需要在程序中做一些耗时的操作,比如:网络请求,文件操作,数据库操作。通常我们都是在子线程中做一些耗时操作,在主线程中更新ui。
(2),Scheduler都有哪些有用的方法呢
(3),当我们创建一个Observable/Flowable默认是在主线程中进行,如下代码:
Flowable.just("Hello World", "Very Good")
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) {
Log.e(TAG, Thread.currentThread().getName());
}
});
//打印结果 main
如上代码,不管是观察者还是被观察者,如果不指定Scheduler,它就是默认的线程。开发过程中往往我们需要指定线程,如何进行变换呢?
Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> e) throws Exception {
Log.e(TAG, "subscribe " + Thread.currentThread().getName());
e.onNext(1);
}
}, BackpressureStrategy.BUFFER);
Consumer<Integer> consumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e(TAG, "accept " + Thread.currentThread().getName());
}
};
flowable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(consumer);
//打印结果 subscribe RxNewThreadScheduler-1
accept main
可以看出,被观察者在子线程中进行,观察者在主线程中进行,主要是因为
subscribeOn(Schedulers.newThread())
observeOn(AndroidSchedulers.mainThread())
subscribeOn()指定上游被观察者的线程,observeOn()指定下游观察者的线程
有关RxJava2.x就简单介绍到这里,如果有时间会做一个项目,系统的使用这个框架。本文并非完全原创,参考了一些文章加上自己的理解,简化了一些内容,没有涉及源码,对于初学者来说容易上手