2.4 RxJava系列7(最佳实践)
2.3 RxJava系列6(从微观角度解读RxJava源码)
2.2 RxJava系列2(基本概念及使用介绍)
2.1 RxJava系列1(简介)
1.1Rxjava之变换操作符
=========
2.4 RxJava系列7(最佳实践)
2.3 RxJava系列6(从微观角度解读RxJava源码)
2.2 RxJava系列2(基本概念及使用介绍)
2.1 RxJava系列1(简介)
前言
因此这篇文章只是简单的通过两个例子介绍了RxJava在生产环境中的使用。不过本篇中的每个例子我都配上了完整的代码。
按照计划这一期是要介绍RxJava框架结构和设计思想的,但是考虑到Netflix将在十月底发布RxJava2.0正式版;因此决定将RxJava框架结构和设计思想分析放到2.0正式版发布后再做。后续我也会有一系列的文章来介绍RxJava1.x和2.x的区别。
示例一、获取手机上已安装的App
第一个例子 这里我主要讲讲如何通过RxJava实现核心功能。
首选我们需要调用系统api来获取所有已安装的app,所以在OnSubscribe
的call
方法中调用getApplicationInfoList()
。
但是getApplicationInfoList()
获取的数据并不能完全满足我们的业务需求:
- 由于我们只需要展示手机上已安装的第三方App,因此需要通过
filter
操作符来过滤掉系统app; ApplicationInfo
并不是我们所需要的类型,因此需要通过map
操作符将其转换为AppInfo
;- 由于获取
ApplicationInfo
、过滤数据、转换数据相对比较耗时,因此需要通过subscribeOn
操作符将这一系列操作放到子线程中来处理; - 而要将信息展示在页面上涉及到UI操作,因此需要通过
observeOn
操作符将onNext
、onCompleted
、onError
调度到主线程,接着我们在这些方法中更新UI。
下面是核心代码:
final PackageManager pm = MainActivity.this.getPackageManager();
Observable.create(new Observable.OnSubscribe<ApplicationInfo>() {
@Override
public void call(Subscriber<? super ApplicationInfo> subscriber) {
List<ApplicationInfo> infoList = getApplicationInfoList(pm);
for (ApplicationInfo info : infoList) {
subscriber.onNext(info);
}
subscriber.onCompleted();
}
}).filter(new Func1<ApplicationInfo, Boolean>() {
@Override
public Boolean call(ApplicationInfo applicationInfo) {
return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0;
}
}).map(new Func1<ApplicationInfo, AppInfo>() {
@Override
public AppInfo call(ApplicationInfo applicationInfo) {
AppInfo info = new AppInfo();
info.setAppIcon(applicationInfo.loadIcon(pm));
info.setAppName(applicationInfo.loadLabel(pm).toString());
return info;
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<AppInfo>() {
@Override
public void onCompleted() {
mAppListAdapter.notifyDataSetChanged();
mPullDownSRL.setRefreshing(false);
}
@Override
public void onNext(AppInfo appInfo) {
mAppInfoList.add(appInfo);
}
});
示例二、RxJava+Retrofit2实现获取天气数据
RxJava + Retrofit2几乎是Android应用开发的标配了,这个例子中我们就来聊聊这二者是如何配合起来帮助我们快速开发的。
Retrofit2中一个标准的接口定义是这样的:
@GET("weather")
Observable<Weather> getWeather(@Query("cityId") String cityId);
现在有了RxJava,一个基本的网络请求我们便可以这样实现:
ApiClient.weatherService.getWeather(cityId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Weather>() {
@Override
public void call(Weather weather) {
weatherView.displayWeatherInformation(weather);
}
});
但有时候可能一开始我们并不知道cityId,我们只知道cityName。所以就需要我们先访问服务器,拿到对应城市名的cityId,然后通过这个cityId再去获取天气数据。
同样的,我们需要定义一个获取cityId的接口:
@GET("city")
Observable<String> getCityIdByName(@Query("cityName") String cityName);
紧接着我们便可以使用无所不能的RxJava来实现需求了。
ApiClient.weatherService.getCityIdByName("上海")
.flatMap(new Func1<String, Observable<Weather>>() {
@Override
public Observable<Weather> call(String cityId) {
return ApiClient.weatherService.getWeather(cityId);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Weather>() {
@Override
public void call(Weather weather) {
weatherView.displayWeatherInformation(weather);
}
});
WeatherStyle这个项目还在开发中,这个项目不只包含了RxJava和Retrofit的使用,同时还包含MVP、ORMLite、RetroLambda、ButterKnife等等开源库的使用
RxJava1.X的系列文章就到此结束了,由于本人对RxJava的理解有限,这一系列文章中如有错误还请大家指正。在使用RxJava过程中有任何疑问也欢迎大家和我交流。共同学习!共同进步!
好啦,我们RxJava2见!~
前言
通过前面五个篇幅的介绍,相信大家对RxJava的基本使用以及操作符应该有了一定的认识。但是知其然还要知其所以然;
所以从这一章开始我们聊聊源码,分析RxJava的实现原理。本文我们主要从三个方面来分析RxJava的实现:
- RxJava基本流程分析
- 操作符原理分析
- 线程调度原理分析
本章节基于RxJava1.1.9版本的源码
一、RxJava执行流程分析
在RxJava系列2(基本概念及使用介绍)中我们介绍过,一个最基本的RxJava调用是这样的:
示例A
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello RxJava!");
subscriber.onCompleted();
}
}).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("completed!");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
System.out.println(s);
}
});
首先调用Observable.create()
创建一个被观察者Observable
,同时创建一个OnSubscribe
作为create()
方法的入参;
接着创建一个观察者Subscriber
,然后通过subseribe()
实现二者的订阅关系。 这里涉及到三个关键对象和一个核心的方法:
- Observable(被观察者)
- OnSubscribe (从纯设计模式的角度来理解,
OnSubscribe.call()
可以看做是观察者模式中被观察者用来通知观察者的notifyObservers()
方法) - Subscriber (观察者)
- subscribe() (实现观察者与被观察者订阅关系的方法)
1、Observable.create()源码分析
首先我们来看看Observable.create()
的实现:
public static <T> Observable<T> create(OnSubscribe<T> f) {
return new Observable<T>(RxJavaHooks.onCreate(f));
}
这里创建了一个被观察者Observable
,同时将RxJavaHooks.onCreate(f)
作为构造函数的参数,源码如下:
protected Observable(OnSubscribe<T> f) {
this.onSubscribe = f;
}
我们看到源码中直接将参数RxJavaHooks.onCreate(f)
赋值给了当前我们构造的被观察者Observable
的成员变量onSubscribe
。那么RxJavaHooks.onCreate(f)
返回的又是什么呢?我们接着往下看:
public static <T> Observable.OnSubscribe<T> onCreate(Observable.OnSubscribe<T> onSubscribe) {
Func1<OnSubscribe, OnSubscribe> f = onObservableCreate;
if (f != null) {
return f.call(onSubscribe);
}
return onSubscribe;
}
由于我们并没调用RxJavaHooks.initCreate()
,所以上面代码中的onObservableCreate
为null;因此RxJavaHooks.onCreate(f)
最终返回的就是f
,也就是我们在Observable.create()
的时候new出来的OnSubscribe
。(由于对RxJavaHooks的理解并不影响我们对RxJava执行流程的分析,因此在这里我们不做进一步的探讨。为了方便理解我们只需要知道RxJavaHooks一系列方法的返回值就是入参本身就OK了,例如这里的RxJavaHooks.onCreate(f)
返回的就是f
)。
至此我们做下逻辑梳理:Observable.create()
方法构造了一个被观察者Observable
对象,同时将new出来的OnSubscribe
赋值给了该Observable
的成员变量onSubscribe
。
2、Subscriber源码分析
接着我们看下观察者Subscriber
的源码,为了增加可读性,我去掉了源码中的注释和部分代码。
public abstract class Subscriber<T> implements Observer<T>, Subscription {
private final SubscriptionList subscriptions;//订阅事件集,所有发送给当前Subscriber的事件都会保存在这里
...
protected Subscriber(Subscriber<?> subscriber, boolean shareSubscriptions) {
this.subscriber = subscriber;
this.subscriptions = shareSubscriptions && subscriber != null ? subscriber.subscriptions : new SubscriptionList();
}
...
@Override
public final void unsubscribe() {
subscriptions.unsubscribe();
}
@Override
public final boolean isUnsubscribed() {
return subscriptions.isUnsubscribed();
}
public void onStart() {
}
...
}
public interface Subscription {
void unsubscribe();
boolean isUnsubscribed();
}
Subscriber
实现了Subscription
接口,从而对外提供isUnsubscribed()
和unsubscribe()
方法。前者用于判断是否已经取消订阅;后者用于将订阅事件列表(也就是当前观察者的成员变量subscriptions
)中的所有Subscription
取消订阅,并且不再接受观察者Observable
发送的后续事件。
3、subscribe()源码分析
前面我们分析了观察者和被观察者相关的源码,那么接下来便是整个订阅流程中最最关键的环节了。
public final Subscription subscribe(Subscriber<? super T> subscriber) {
return Observable.subscribe(subscriber, this);
}
static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
...
subscriber.onStart();
if (!(subscriber instanceof SafeSubscriber)) {
subscriber = new SafeSubscriber<T>(subscriber);
}
try {
RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
return RxJavaHooks.onObservableReturn(subscriber);
} catch (Throwable e) {
...
return Subscriptions.unsubscribed();
}
}
subscribe()
方法中将传进来的subscriber
包装成了SafeSubscriber
,SafeSubscriber
其实是subscriber
的一个代理,对subscriber
的一系列方法做了更加严格的安全校验。保证了onCompleted()
和onError()
只会有一个被执行且只执行一次,一旦它们其中方法被执行过后onNext()
就不在执行了。
上述代码中最关键的就是RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber)
。这里的RxJavaHooks和之前提到的一样,RxJavaHooks.onObservableStart(observable, observable.onSubscribe)
返回的正是他的第二个入参observable.onSubscribe
,也就是当前observable
的成员变量onSubscribe
。而这个成员变量我们前面提到过,它是我们在Observable.create()
的时候new出来的。所以这段代码可以简化为onSubscribe.call(subscriber)
。这也印证了我在RxJava系列2(基本概念及使用介绍)中说的,onSubscribe.call(subscriber)
中的subscriber
正是我们在subscribe()
方法中new出来的观察者。
到这里,我们对RxJava的执行流程做个总结:首先我们调用crate()
创建一个观察者,同时创建一个OnSubscribe
作为该方法的入参;接着调用subscribe()
来订阅我们自己创建的观察者Subscriber
。
一旦调用subscribe()
方法后就会触发执行OnSubscribe.call()
。然后我们就可以在call方法调用观察者subscriber
的onNext()
,onCompleted()
,onError()
。
最后我用张图来总结下之前的分析结果:
二、操作符原理分析
之前我们介绍过几十个操作符,要一一分析它们的源码显然不太现实。在这里我抛砖引玉,选取一个相对简单且常用的map
操作符来分析。
我们先来看一个map
操作符的简单应用:
示例B
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(1);
subscriber.onCompleted();
}
}).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return "This is " + integer;
}
}).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("onCompleted!");
}
@Override
public void onError(Throwable e) {
System.out.println(e.getMessage());
}
@Override
public void onNext(String s) {
System.out.println(s);
}
});
为了便于表述,我将上面的代码做了如下拆解:
Observable<Integer> observableA = Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(1);
subscriber.onCompleted();
}
});
Subscriber<String> subscriberOne = new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("onCompleted!");
}
@Override
public void onError(Throwable e) {
System.out.println(e.getMessage());
}
@Override
public void onNext(String s) {
System.out.println(s);
}
};
Observable<String> observableB =
observableA.map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return "This is " + integer;;
}
});
observableB.subscribe(subscriberOne);
map()
的源码和上一小节介绍的create()
一样位于Observable
这个类中。
public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
return create(new OnSubscribeMap<T, R>(this, func));
}
通过查看源码我们发现调用map()
的时候实际上是创建了一个新的被观察者Observable
,我们姑且称它为ObservableB
;一开始通过Observable.create()
创建的Observable
我们称之为ObservableA
。在创建ObservableB
的时候同时创建了一个OnSubscribeMap
,而ObservableA
和变换函数Func1
则作为构造OnSubscribeMap
的参数。
public final class OnSubscribeMap<T, R> implements OnSubscribe<R> {
final Observable<T> source;//ObservableA
final Func1<? super T, ? extends R> transformer;//map操作符中的转换函数Func1。T为转换前的数据类型,在上面的例子中为Integer;R为转换后的数据类型,在该例中为String。
public OnSubscribeMap(Observable<T> source, Func1<? super T, ? extends R> transformer) {
this.source = source;
this.transformer = transformer;
}
@Override
public void call(final Subscriber<? super R> o) {//结合第一小节的分析结果,我们知道这里的入参o其实就是我们自己new的观察者subscriberOne。
MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
o.add(parent);
source.unsafeSubscribe(parent);
}
static final class MapSubscriber<T, R> extends Subscriber<T> {
final Subscriber<? super R> actual;//这里的actual就是我们在调用subscribe()时创建的观察者mSubscriber
final Func1<? super T, ? extends R> mapper;//变换函数
boolean done;
public MapSubscriber(Subscriber<? super R> actual, Func1<? super T, ? extends R> mapper) {
this.actual = actual;
this.mapper = mapper;
}
@Override
public void onNext(T t) {
R result;
try {
result = mapper.call(t);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
unsubscribe();
onError(OnErrorThrowable.addValueAsLastCause(ex, t));
return;
}
actual.onNext