- 简单的介绍
- 简单的用法
- 各操作符
- 实际的项目运用
介绍
很多博客都写的很清楚了,先推荐一些入门挺好的博客:
关于 RxJava 最友好的文章—— RxJava 2.0 全新来袭
给 Android 开发者的 RxJava 详解
然后说说这个东西的核心:观察者模式。
这里的 Observe 会被 Observable 的事件主动的触发。
也就是 Observe 的方法不会被显性的调用,而是等待 Observable 的呼叫。
其实关于这个相信大家都不是第一次接触,比如 ListView 、 Button 的OnClick 等事件,就是利用的观察者模式。这时候 ListView 就是 Observable ,OnClick 事件就是 Ovserve
当然 RxJava 最厉害的还是它的异步操作
相对于其他的异步的方法 AsyncTask 、Handler 等,它的流式API调用风格和各种操作符可以让程序越来越复杂的情况下依然保持代码的清晰,
注意它并不能让代码变得简单,而是清晰,也就是易读
RxJava 1 和 RxJava 2 的区别最大在于 背压 的实现方法变了
关于 RxJava 最友好的文章——背压(Backpressure)
简单介绍这个概念:
在原来框架中,被观察者 Observable 会主动向 观察者 Observer 发送事件。
而利用背压这个策略的时候,Observer 会向 Observable 发送请求,Observable 收到请求后才会发送事件。
原因是如果 Observer 处理事件的速度远远慢于 Observable 发送的速度,会使得内存泄露。
基础的方法
创建 Observable 和 Observer
不支持背压
最基础的调用:
Observable mObservable=Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onComplete();
}
});
Observer mObserver=new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
//订阅之后、发送数据之前被调用
//可以使用d.dispose()方法来取消订阅
}
@Override
public void onNext(Integer value) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
mObservable.subscribe(mObserver);//这句如果漏掉了就不能让这两个对象产生联系
创建 Flowable 和 Subscriber
支持背压
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> e) throws Exception {
e.onNext("Hello,I am China!");
}
}, BackpressureStrategy.BUFFER).subscribe(subscriber);
//需要指定背压策略,BUFFER
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
//初始化操作,调用 request() 方法表示初始化工作已经完成,立即触发 onNext () 方法
//在 onComplete() 方法完成,才会再执行 request() - 后边的代码
Log.w("TAG","onsubscribe start");
s.request(1);//请求数据
Log.w("TAG","onsubscribe end");
}
@Override
public void onNext(String value) {
Log.e("onNext", value);
sub.request(1);//继续请求数据
}
@Override
public void onError(Throwable t) {
Log.e("onError", t.getMessage());
}
@Override
public void onComplete() {
Log.e("onComplete", "complete");
}
};
上面的代码输出语句顺序为:
onsubscribe start
onNext
onComplete
onsubscribe end
FLowable 和 Observable 还有很多别的创建方式:
//第一个参数为起始值,第二个为发送的个数,如果为0则不发送,负数则抛异常。
//即调用20次 onNext() 方法,依次传入数字 1 - 20
Flowable f = Flowable.range(0,10);
// 按固定时间间隔发射整数序列,即按照固定2秒一次调用onNext()方法。
//TimeUnit 是 java 工具类,可以换单位 TimeUnit.HOURS
Observable o = Observable.interval(2, TimeUnit.SECONDS)
Observable<String> o = Observable.just("Hello");
不一一列出
各类型操作符与实际的项目运用
类型转换
- flatMap() //与 map 类似,不同于用于将一个对象加工成另一个对象的数组
- map() //在事件传递过程中,转换传递的对象的类型
- filter() // 根据重写的 test() 方法中的判断语句,返回 true 则表示数据满足条件,返回 false 则表示数据需要被过滤。
线程变换
subscribeOn()//它指示 Observable 在一个指定的调度器上创建(只作用于被观察者创建阶段)。只能指定一次,如果指定多次则以第一次为准
observeOn()//指定在事件传递(加工变换)和最终被处理(观察者)的发生在哪一个调度器。可指定多次,每次指定完都在下一步生效。
下面是一个实际的操作,流式 api 调用风格:
由 String 型的 url 通过异步网络请求后,将得到的 JSON 转换成想要的数据
上面的操作符都有详细的注释
String News_URL = "http://xxxx";
//这一句创建一个 observable 对象,并用将 News_URL 传递下去
Observable.fromArray(News_URL)
//指定在新线程中创建被观察者 observable
.subscribeOn(Schedulers.newThread())
//map 将 fromArray() 传入的 News_URL (String) 变成 JSONObject 对象
.map(new Function<String, JSONObject>() {
@Override
public JSONObject apply(String s) throws Exception {
//参数 s 就是上面传进来的 News_URL
URL new_url=new URL(s);
//调用自己写的方法,一些网络请求,不是重点
JSONObject jsonObject= getData.URL2JSONObject(new_url);
//返回 JSONObject 类型的对象,完成了转换
return jsonObject;
}
})
//map 返回的 JSONObject 对应这里的第一个参数
.flatMap(new Function<JSONObject, ObservableSource<JSONObject>>() {
@Override
public ObservableSource<JSONObject> apply(JSONObject jsonObject) throws Exception {
//jsonObject 就是 map 返回的对象
JSONArray stories = jsonObject.getJSONArray("stories");
JSONObject[] jsonObjectsList = new JSONObject[stories.length()];
//这一段不是重点,
for (int i = 0;i < stories.length();i++){
jsonObjectsList[i]= stories.getJSONObject(i);
}
//flatMap 的重点在于这里
//看上面的 Function<JSONObject, ObservableSource<JSONObject> 可以知道
//flatMap 返回的对象是由第二个参数指定,即 ObservableSource<JSONObject>
//但这里实际 return 了一个 JSONObject [] ,一个数组
//因为 flatMap 会把这个数组里的对象逐个传递到下面的 onNext 中
return Observable.fromArray(jsonObjectsList);
}
})
//切换线程,将这句代码以下的操作放到主线程中
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<JSONObject>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(JSONObject jO) {
try {
//这一段代码会被多次执行
//执行次数由上面的 flatMap 里的 jsonObjectsList 的长度决定
News news=new News();
String url = null;
url = jO.getJSONArray("images").getString(0).toString();
news.setImages(url);
news.setTitle(jO.getString("title"));
news.setId(jO.getString("id"));
newss.add(news);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
ListView newslistView=(ListView) view.findViewById(R.id.show_news);
newAdapter = new NewsAdapter(newss,mcontext,newslistView);
newslistView.setAdapter(newAdapter);
}
});
关于线程的切换:
下面这段代码来自关于 RxJava 最友好的文章
//new Observable.just()执行在新线程
Observable.just(getFilePath())
//指定在新线程中创建被观察者
.subscribeOn(Schedulers.newThread())
//将接下来执行的线程环境指定为io线程
.observeOn(Schedulers.io())
//map就处在io线程
.map(mMapOperater)
//将后面执行的线程环境切换为主线程,
//但是这一句依然执行在io线程
.observeOn(AndroidSchedulers.mainThread())
//指定线程无效,但这句代码本身执行在主线程
.subscribeOn(Schedulers.io())
//执行在主线程
.subscribe(mSubscriber);
感谢 拉丁吴 的博客,他还写有另一篇关于 RxJava 的进阶内容:
关于RxJava最友好的文章(进阶)
这里都是简单的笔记,后续如果深入源码会继续更新。