rxjava
Rx介绍
ReactiveX的历史
ReactiveX是Reactive Extensions的缩写,一般简写为Rx,最初是LINQ的一个扩展,由微软的架构师Erik Meijer领导的团队开发,在2012年11月开源,Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流,Rx库支持.NET、JavaScript和C++,Rx近几年越来越流行了,现在已经支持几乎全部的流行编程语言了,Rx的大部分语言库由ReactiveX这个组织负责维护,比较流行的有RxJava/RxJS/Rx.NET,社区网站是 reactivex.io。
什么是ReactiveX
微软给的定义是,Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序,使用Rx,开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流, 用Schedulers参数化异步数据流的并发处理,Rx可以这样定义:Rx = Observables + LINQ + Schedulers。
ReactiveX.io给的定义是,Rx是一个使用可观察数据流进行异步编程的编程接口,ReactiveX结合了观察者模式、迭代器模式和函数式编程的精华。
ReactiveX的应用
很多公司都在使用ReactiveX,例如Microsoft、Netflix、Github、Trello、SoundCloud。
ReactiveX宣言
ReactiveX不仅仅是一个编程接口,它是一种编程思想的突破,它影响了许多其它的程序库和框架以及编程语言。
Rx模式
使用观察者模式
-
创建:Rx可以方便的创建事件流和数据流
-
组合:Rx使用查询式的操作符组合和变换数据流
-
监听:Rx可以订阅任何可观察的数据流并执行操作
简化代码
-
函数式风格:对可观察数据流使用无副作用的输入输出函数,避免了程序里错综复杂的状态
-
简化代码:Rx的操作符通通常可以将复杂的难题简化为很少的几行代码
-
异步错误处理:传统的try/catch没办法处理异步计算,Rx提供了合适的错误处理机制
-
轻松使用并发:Rx的Observables和Schedulers让开发者可以摆脱底层的线程同步和各种并发问题
使用Observable的优势
Rx扩展了观察者模式用于支持数据和事件序列,添加了一些操作符,它让你可以声明式的组合这些序列,而无需关注底层的实现:如线程、同步、线程安全、并发数据结构和非阻塞IO。
Observable通过使用最佳的方式访问异步数据序列填补了这个间隙
Observable无偏见
Rx对于对于并发性或异步性没有任何特殊的偏好,Observable可以用任何方式实现,线程池、事件循环、非阻塞IO、Actor模式,任何满足你的需求的,你擅长或偏好的方式都可以。无论你选择怎样实现它,无论底层实现是阻塞的还是非阻塞的,客户端代码将所有与Observable的交互都当做是异步的
响应式编程
Rx提供了一系列的操作符,你可以使用它们来过滤(filter)、选择(select)、变换(transform)、结合(combine)和组合(compose)多个Observable,这些操作符让执行和复合变得非常高效。
你可以把Observable当做Iterable的推送方式的等价物,使用Iterable,消费者从生产者那拉取数据,线程阻塞直至数据准备好。使用Observable,在数据准备好时,生产者将数据推送给消费者。数据可以同步或异步的到达,这种方式更灵活。
入门链接:
https://www.jianshu.com/p/cd3557b1a474
https://www.cnblogs.com/lyysz/p/6344507.html
https://www.cnblogs.com/liushilin/p/7058302.html
https://www.jb51.net/article/92309.html
https://zhuanlan.zhihu.com/p/31413825
rxjava2.0与3.0差异化
基本使用
最基本的使用
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("连载1");
emitter.onNext("连载2");
emitter.onNext("连载3");
emitter.onComplete();
}
})
.observeOn(AndroidSchedulers.mainThread())//回调在主线程
.subscribeOn(Schedulers.io())//执行在io线程
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG,"onSubscribe");
}
@Override
public void onNext(String value) {
Log.e(TAG,"onNext:"+value);
}
@Override
public void onError(Throwable e) {
Log.e(TAG,"onError="+e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete()");
}
});
使用Consumer省略多余的回调,只接受结束以后的,subscribeOn指定被观察者的线程,observeOn指定观察者的线程
Observable.create(new ObservableOnSubscribe<Drawable>() {
@Override
public void subscribe(ObservableEmitter<Drawable> emitter) throws Exception {
for (int i=0;i<drawableRes.length;i++){
Drawable drawable=getResources().getDrawable(drawableRes[i]);
//第6个图片延时3秒后架子
if (i==5){
sleep(3000);
}
//复制第7张图片到sd卡
if (i==6){
Bitmap bitmap=((BitmapDrawable)drawable).getBitmap();
saveBitmap(bitmap,"test.png", Bitmap.CompressFormat.PNG);
}
//上传到网络
if (i==7){
updateIcon(drawable);
}
emitter.onNext(drawable);
}
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Drawable>() {
@Override
public void accept(Drawable drawable) throws Exception {
//回调后在UI界面上展示出来
}
});
RXJava配合Retrofit基本使用
public interface WangAndroidApi {
// 总数据
@GET("project/tree/json")
Observable<ProjectBean> getProject(); // 异步线程 耗时操作
// ITem数据
@GET("project/list/{pageIndex}/json") // ?cid=294
Observable<ProjectItem> getProjectItem(@Path("pageIndex") int pageIndex, @Query("cid") int cid); // 异步线程 耗时操作
}
/**
* TODO Retrofit+RxJava 查询 项目分类 (总数据查询)
*
* @param view
*/
public void getProjectAction(View view) {
// 获取网络API
api.getProject()
.subscribeOn(Schedulers.io()) // 上面 异步
.observeOn(AndroidSchedulers.mainThread()) // 下面 主线程
.subscribe(new Consumer<ProjectBean>() {
@Override
public void accept(ProjectBean projectBean) throws Exception {
Log.d(TAG, "accept: " + projectBean); // UI 可以做事情
}
});
}
防抖
使用RXView,进行防抖的操作
过度嵌套的操作
// 注意:(项目分类)查询的id,通过此id再去查询(项目列表数据)
// 对那个控件防抖动?
Button bt_anti_shake = findViewById(R.id.bt_anti_shake);
RxView.clicks(bt_anti_shake)
.throttleFirst(2000, TimeUnit.MILLISECONDS) // 2秒钟之内 响应你一次
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
api.getProject() // 查询主数据
.compose(DownloadActivity.rxud())
.subscribe(new Consumer<ProjectBean>() {
@Override
public void accept(ProjectBean projectBean) throws Exception {
for (ProjectBean.DataBean dataBean : projectBean.getData()) { // 10
// 查询item数据
api.getProjectItem(1, dataBean.getId())
.compose(DownloadActivity.rxud())
.subscribe(new Consumer<ProjectItem>() {
@Override
public void accept(ProjectItem projectItem) throws Exception {
Log.d(TAG, "accept: " + projectItem); // 可以UI操作
}
});
}
}
});
}
});
使用flatmap的操作
// 注意:项目分类查询的id,通过此id再去查询(项目列表数据)
// 对那个控件防抖动?
Button bt_anti_shake = findViewById(R.id.bt_anti_shake);
RxView.clicks(bt_anti_shake)
.throttleFirst(2000, TimeUnit.MILLISECONDS) // 2秒钟之内 响应你一次
// 我只给下面 切换 异步
.observeOn(Schedulers.io())
.flatMap(new Function<Object, ObservableSource<ProjectBean>>() {
@Override
public ObservableSource<ProjectBean> apply(Object o) throws Exception {
return api.getProject(); // 主数据
}
})
// 第一步不能map 因为 api Observbale<Bean> TODO 小作业 同学们自己尝试
/*.map(new Function<Object, ObservableSource<ProjectBean>>() {
@Override
public ObservableSource<ProjectBean> apply(Object o) throws Exception {
return api.getProject(); // 主数据;
}
})*/
.flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataBean>>() {
@Override
public ObservableSource<ProjectBean.DataBean> apply(ProjectBean projectBean) throws Exception {
return Observable.fromIterable(projectBean.getData()); // 我自己搞一个发射器 发多次 10
}
})
.flatMap(new Function<ProjectBean.DataBean, ObservableSource<ProjectItem>>() {
@Override
public ObservableSource<ProjectItem> apply(ProjectBean.DataBean dataBean) throws Exception {
return api.getProjectItem(1, dataBean.getId());
}
})
.observeOn(AndroidSchedulers.mainThread()) // 给下面切换 主线程
.subscribe(new Consumer<ProjectItem>() {
@Override
public void accept(ProjectItem projectItem) throws Exception {
// 如果我要更新UI 会报错2 不会报错1
Log.d(TAG, "accept: " + projectItem);
}
});
doOnNext
doOnNext()允许我们在每次输出一个元素之前做一些额外的事情。比如如下的例子,在第一个注册完成之后,调用deOnNext进行插入操作,然后在进行最后的subscribe操作,相当于插入了操作.
/**
* TODO
* Retrofit + RxJava
* 需求:
* 1.请求服务器注册操作
* 2.注册完成之后,更新注册UI
* 3.马上去登录服务器操作
* 4.登录完成之后,更新登录的UI
*
* wy.RxJava配合Retrofit。
* RxJava + Retrofit (请求网络OkHttp ---- Retorfit --- Observable)
*
* 1.OkHttp 请求网络 (Retorfit)
* 2.Retorfit 返回一个结果 (Retorfit) --- Observable
* 3.最终的结果 是RxJava中的 被观察者 上游 Observable
* 4.一行代码写完需求流程: 从上往下
* 1.请求服务器,执行注册操作(耗时)切换异步线程
* 2.更新注册后的所有 注册相关UI - main 切换主线程
* 3.请求服务器,执行登录操作(耗时)切换异步线程
* 4.更新登录后的所有 登录相关UI - main 切换主线程
*
* 5.看RxJava另外一种的执行流程
* 初始点 开始点 订阅
* 1.onSubscribe
* 2.registerAction(new RegisterRequest())
* 3..doOnNext 更新注册后的 所有UI
* 4.flatMap执行登录的耗时操作
* 5.订阅的观察者 下游 onNext 方法,更新所有登录后的UI
* 6.progressDialog.dismiss()
*/
public class RequestActivity extends AppCompatActivity {
private final String TAG = RequestActivity.class.getSimpleName();
private TextView tv_register_ui;
private TextView tv_login_ui;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_request);
tv_register_ui = findViewById(R.id.tv_login_ui);
tv_login_ui = findViewById(R.id.tv_login_ui);
}
// TODO 方式一 分开写
@SuppressLint("CheckResult")
public void request(View view) {
// 1.请求服务器注册操作
// 2.注册完成之后,更新注册UI
MyRetrofit.createRetrofit().create(IReqeustNetwor.class)
.registerAction(new RegisterRequest())
.compose(DownloadActivity.rxud())
.subscribe(new Consumer<RegisterResponse>() {
@Override
public void accept(RegisterResponse registerResponse) throws Exception {
// 更新注册相关的所有UI
// .....
}
});
// 分开写
// 3.马上去登录服务器操作
// 4.登录完成之后,更新登录的UI
MyRetrofit.createRetrofit().create(IReqeustNetwor.class)
.loginAction(new LoginReqeust())
.compose(DownloadActivity.rxud())
.subscribe(new Consumer<LoginResponse>() {
@Override
public void accept(LoginResponse loginResponse) throws Exception {
// 更新登录相关的所有UI
// .....
}
});
}
/**
* TODO ================= 下面是一行代码完成整个需求
*/
private ProgressDialog progressDialog;
Disposable disposable;
public void request2(View view) {
/**
* 一行代码 实现需求
* 需求:
* 还有弹出加载
* * 1.请求服务器注册操作
* * 2.注册完成之后,更新注册UI
* * 3.马上去登录服务器操作
* * 4.登录完成之后,更新登录的UI
*/
MyRetrofit.createRetrofit().create(IReqeustNetwor.class)
.registerAction(new RegisterRequest()) // todo 1.请求服务器注册操作 // todo 2
.subscribeOn(Schedulers.io()) // 给上面 异步
.observeOn(AndroidSchedulers.mainThread()) // 给下面分配主线程
.doOnNext(new Consumer<RegisterResponse>() { // todo 3
@Override
public void accept(RegisterResponse registerResponse) throws Exception {
// todo 2.注册完成之后,更新注册UI
}
})
// todo 3.马上去登录服务器操作
.observeOn(Schedulers.io()) // 给下面分配了异步线程
.flatMap(new Function<RegisterResponse, ObservableSource<LoginResponse>>() { // todo 4
@Override
public ObservableSource<LoginResponse> apply(RegisterResponse registerResponse) throws Exception {
Observable<LoginResponse> loginResponseObservable = MyRetrofit.createRetrofit().create(IReqeustNetwor.class)
.loginAction(new LoginReqeust());
return loginResponseObservable;
}
})
.observeOn(AndroidSchedulers.mainThread()) // 给下面 执行主线程
.subscribe(new Observer<LoginResponse>() {
// 一定是主线程,为什么,因为 subscribe 马上调用onSubscribe
@Override
public void onSubscribe(Disposable d) {
// TODO 1
progressDialog = new ProgressDialog(RequestActivity.this);
progressDialog.show();
// UI 操作
disposable = d;
}
@Override
public void onNext(LoginResponse loginResponse) { // todo 5
// TODO 4.登录完成之后,更新登录的UI
}
@Override
public void onError(Throwable e) {
}
// todo 6
@Override
public void onComplete() {
// 杀青了
if (progressDialog != null) {
progressDialog.dismiss();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// 必须这样写,最起码的标准
if (disposable != null)
if (!disposable.isDisposed())
disposable.dispose();
}
}
RXJAVA源码解析
首先了解一下如何hook rxjava,上图
hook方法,可以hook住所有的observable
RxJavaPlugins.setOnObservableAssembly(new Function<Observable, Observable>() {
@Override
public Observable apply(Observable observable) throws Exception {
Log.d(Flag.TAG, "apply: 整个项目 全局 监听 到底有多少地方使用 RxJava:" + observable);
// 伪代码
/*if (observable === ObservableMap)
return null;*/
return null; // 不破坏人家的功能
}
});
那么为什么可以hook住呢
observable提供了一个回调函数,将监听赋给了onObservableAssembly
@SuppressWarnings("rawtypes")
public static void setOnObservableAssembly(@Nullable Function<? super Observable, ? extends Observable> onObservableAssembly) {
if (lockdown) {
throw new IllegalStateException("Plugins can't be changed anymore");
}
RxJavaPlugins.onObservableAssembly = onObservableAssembly;
}
在起初create的时候,有一个RxJavaPlugins的方法,调用了onAssembly
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
然后调用到这里,apply里面监听使用了onObservableAssembly.apply,然后就可以开心回调啦。可以用于调试hook了啥
@NonNull
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
@NonNull
static <T, R> R apply(@NonNull Function<T, R> f, @NonNull T t) {
try {
return f.apply(t);
} catch (Throwable ex) {
throw ExceptionHelper.wrapOrThrow(ex);
}
}
下面正式分析怎么实现响应式编程的:
RxJava的观察者模式,rxjava并不是严格的观察者模式,普通的观察者模式一般是由被观察者订阅观察者,(简单的一个例子,被观察者内部持有保存了观察者的引用,一旦被观察者发出消息,便可以统一发送消息)
在rxjava里面是一个u形的线式调用,先逐步订阅,然后在一次调用onNext完成整个流程
1、先了解一下订阅流程:上图
一、最简单的情况
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
public void subscribe(ObservableEmitter<Object> e) throws Exception {
e.onNext("A");
}
})
.subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull Boolean aBoolean) {
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
}) ;
从create开始,最后其实就是返回了ObservableCreate包装的对象。
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
@NonNull
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
来看一下这个对象,我们先记住subscribeActual这个方法
public final class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
observer.onSubscribe(parent);
try {
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable{....}
static final class SerializedEmitter<T>
extends AtomicInteger
implements ObservableEmitter<T>{.....}
}
在这个方法里使用了传入进来的observer调用了创建出来的发射器,
observer.onSubscribe(parent);那这个observer是谁呢?至此我们完成了create的订阅步骤。
我们知道了create出来的是一个ObservableCreate的对象,然后我们来看一下.subscribe干了什么
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(Consumer<? super T> onNext) {
return subscribe(onNext, Functions.ON_ERROR_MISSING, Functions.EMPTY_ACTION, Functions.emptyConsumer());
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete, Consumer<? super Disposable> onSubscribe) {
ObjectHelper.requireNonNull(onNext, "onNext is null");
ObjectHelper.requireNonNull(onError, "onError is null");
ObjectHelper.requireNonNull(onComplete, "onComplete is null");
ObjectHelper.requireNonNull(onSubscribe, "onSubscribe is null");
LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);
subscribe(ls);//here
return ls;
}
@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
subscribeActual(observer);//here
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Disposable has been set or not
// can't call onSubscribe because the call might have set a Subscription already
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
//调用了这个抽象方法
protected abstract void subscribeActual(Observer<? super T> observer);
这里面调用了抽象方法subscribeActual,而.subscribe又是由ObservableCreate对象调用的的,ObservableCreate继承了Observable,所以也就调用了我们之前看到的subscribeActual方法。
原来直到使用.subscribe的时候才触发了这个方法,远远在订阅完成之后的,那这个时候就知道了subscribeActual里面的observer是谁了吧,就是create里面传进来的观察者
.subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
//一订阅就调用
}
@Override
public void onNext(@NonNull Boolean aBoolean) {
//最后会回到这里
}
@Override
public void onError(@NonNull Throwable e) {
//报错
}
@Override
public void onComplete() {
//事件结束
}
}) ;
所以订阅调用create就会首先调用onSubscribe的方法
再回到ObservableCreate类里面,触发了onSubscribe方法之后调用了
source.subscribe(parent);
parent就是一开始create传进来的对象,由此回调到了这里来进行操作分发,返回的参数就是创建的发射器,如果我们调用一下e.onNext,就可以将数据向下发射了。
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
public void subscribe(ObservableEmitter<Object> e) throws Exception {
e.onNext("A");
}
})
发射的方法,在ObservableCreate,有发射的类,看一下调到了哪里
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
private static final long serialVersionUID = -3434801548987643227L;
final Observer<? super T> observer;
CreateEmitter(Observer<? super T> observer) {
this.observer = observer;
}
@Override
public void onNext(T t) {
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (!isDisposed()) {
observer.onNext(t);///here
}
}
@Override
public void onError(Throwable t) {
if (!tryOnError(t)) {
RxJavaPlugins.onError(t);
}
}
@Override
public boolean tryOnError(Throwable t) {
if (t == null) {
t = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
}
if (!isDisposed()) {
try {
observer.onError(t);
} finally {
dispose();
}
return true;
}
return false;
}
@Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
dispose();
}
}
}
}
还记得吗,这里的observer是subscribeActual传进来的,是.subscribe(new Observer<Boolean>() )中的对象
observer.onNext(t)的方法一调用,就会回调到我们的主线程里面了,完成了下发
总结起来就是在调用subscribe之前,我们只是创建了create的订阅,相当于从上游(被观察者)走向了下游(观察者)。调用了subscribe这个方法之后,回调了下游的方法,完成监听并发射数据之后,触发了上游的对象
最终完成了数据的响应式编程,u形结构,可以说和观察者模式是有区别的
可以看作是不断新建上游的被观察者来操纵数据,最后反馈给上由一个观察者,属于多个被观察者和一个观察者(Observer),观察者模式是一个被观察者,多个观察者
二,稍微复杂的情况
完成create的分析,下面增加难度,新增一个map
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
public void subscribe(ObservableEmitter<Object> e) throws Exception {
e.onNext("A");
}
})
// null.map
.map(new Function<Object, Boolean>() {
@Override
public Boolean apply(Object o) throws Exception {
return true;
}
})
.subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull Boolean aBoolean) {
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
}) ;
来分析一下map干了些什么,首先要明白是谁调用的map,要记得,是ObservableOnSubscribe对象,然后点进去看一下,还是那个熟悉的味道,最终返回的是ObservableMap对象,一样的套路
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
这里面还是有一个熟悉的方法subscribeActual
至此,完成了被观察者ObservableMap的订阅
public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
final Function<? super T, ? extends U> function;
public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
super(source);
this.function = function;
}
@Override
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
final Function<? super T, ? extends U> mapper;
MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {...}
}
然后我们和第一部分的代码一起来走一遍流程,是怎么调用的
1、创建ObservableOnSubscribe订阅
2、创建ObservableMap订阅
3、当我们开始使用.subscribe进行订阅的时候,这个时候是离得最近的ObservableMap调用了subscribe开始订阅,触发subscribe方法里面的
protected abstract void subscribeActual(Observer<? super T> observer);
也就是触发了ObservableMap的subscribeActual,我们发现没有做什么,就是使用MapObserver打包了一下,然后讲打包一起丢给了这个source的方法
@Override
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
看一下这个包装了什么,调用了apply,也就是我们在主流程里面回调的方法.,在这里实现了,调用完成后触发onNext,onNext是subscribeActual传进来的,也就是最终观察者的onNext完成的状态,但是在这之前,因为我们有source的调用,所以在这里是先走了source的方法,那么source是啥呢
static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
final Function<? super T, ? extends U> mapper;
MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
super(actual);
this.mapper = mapper;
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
actual.onNext(null);
return;
}
U v;
try {
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
actual.onNext(v);
}
}
还记得这个source吗,这个是ObservableMap初始化带进来的,这个this,就是调用map的ObservableOnSubscribe,走到这里又走回去开始调用ObservableOnSubscribe的方法了
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
ObservableOnSubscribe继承自Observable的,自己没有这个方法,就调用了父类Observable的,这个时候实际上就回到了第一步的流程了,开始调用ObservableCreate,以及其下的方法
@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Disposable has been set or not
// can't call onSubscribe because the call might have set a Subscription already
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
但是呢,第一大部分里面我们是最终的观察者来发起的订阅触发的ObservableOnSubscribe,而这里却是ObservableMap,所以触发的也是ObservableMap的onNext,往上翻一下,看一下MapObserver的onNext是不是开始调用最终观察者的onNext了,
4、经过了订阅ObservableOnSubscribe----ObservableMap-----Observer.subscribe------ObservableMap.subscribeActual-----ObservableOnSubscribe.subscribeActual------ObservableOnSubscribe的onNext--ObservableMap的onNext---Observer的onNext终于完成了整个调用链条
再看一下一开始贴的流程图,是不是很清晰的u形调用逻辑,至此.基本的调用链条走完了,累......
三、切换线程的分析
对于我们Android开发来说,最喜欢的就是它简洁切换线程的操作。RxJava通过调度器来方便线程的切换。
- Schedulers.computation(): 适合运行在密集计算的操作,大多数异步操作符使用该调度器。
- Schedulers.io():适合运行I/0和阻塞操作.
- Schedulers.single():适合需要单一线程的操作
- Schedulers.trampoline(): 适合需要顺序运行的操作
- 在不同平台还有不同的调度器,例如Android的主线程:
AndroidSchedulers.mainThread()
我们在使用期间会使用observeOn以及subsceOn来实现线程的切换调度,不断地在主线程和子线程切换,这玩意儿是咋做到的呢
我先贴个链接,了解了以后可以再看一下
为什么subscribeOn第一次执行生效,observeOn每次执行都生效?
然后上图
subscribeOn
Observable.create(
// 自定义source
new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("Derry");
Log.d(L.TAG, "自定义source: " + Thread.currentThread().getName());
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
)
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
点进来看看,这是啥,是不是还是那一套,这里是订阅了ObservableSubscribeOn,
这里再看一下observeOn,对那个是ObservableObserveOn,名字很像,不要整混了.
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler) {
return observeOn(scheduler, false, bufferSize());
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}
其实就是在这两个被观察者里面实现的线程的切换,还记得开始的时候抛出的问题么,为什么连续调用几个方法的时候,二者触发的流程不一样(为什么subscribeOn第一次执行生效,observeOn每次执行都生效?)
// subsceOn(1) // 会显示是这个线程的原因,上一层卡片是被1线程执行
// subsceOn(2)
// subsceOn(3)
// observeOn(A)
// observeOn(B)
// observeOn(C) // 终点是被C执行
来看一下二者源码
看到了吗.ObservableSubscribeOn的切换执行是在subscribeActual里面进行切换的,SubscribeTask就是一个Runnable,内部是使用线程池进行线程的切换,
而subscribeActual是在自下而上触发subscribeActual的时候切换的,所以从下而上,第一个才是实际切换的线程
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
s.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));//在这就开始线程的切换了
}
static final class SubscribeOnObserver<T> extends AtomicReference<Disposable> implements Observer<T>, Disposable {
private static final long serialVersionUID = 8094547886072529208L;
final Observer<? super T> actual;
final AtomicReference<Disposable> s;
SubscribeOnObserver(Observer<? super T> actual) {
this.actual = actual;
this.s = new AtomicReference<Disposable>();
}
@Override
public void onSubscribe(Disposable s) {
DisposableHelper.setOnce(this.s, s);
}
@Override
public void onNext(T t) {
actual.onNext(t);
}
@Override
public void onError(Throwable t) {
actual.onError(t);
}
@Override
public void onComplete() {
actual.onComplete();
}
@Override
public void dispose() {
DisposableHelper.dispose(s);
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
void setDisposable(Disposable d) {
DisposableHelper.setOnce(this, d);
}
}
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
}
而在ObservableObserveOn的方法里subscribeActual只是创建了线程调度的Scheduler.Worker w = scheduler.createWorker();
直到onNext里面 schedule()方法才开始执行线程的切换,以后每一步onNext都会在新切换的线程执行,所以会执行最后一个的切换,只要整个流程弄明白了,这里就很容易理解
多说一句,这里执行的是切换主线程的操作的时候使用的是handler切换的主线程
new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
// UI 操作 ...
}
};
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
final boolean delayError;
final int bufferSize;
public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
super(source);
this.scheduler = scheduler;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
implements Observer<T>, Runnable {
.......
ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
this.actual = actual;
this.worker = worker;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.validate(this.s, s)) {
this.s = s;
if (s instanceof QueueDisposable) {
@SuppressWarnings("unchecked")
QueueDisposable<T> qd = (QueueDisposable<T>) s;
int m = qd.requestFusion(QueueDisposable.ANY | QueueDisposable.BOUNDARY);
if (m == QueueDisposable.SYNC) {
sourceMode = m;
queue = qd;
done = true;
actual.onSubscribe(this);
schedule();
return;
}
if (m == QueueDisposable.ASYNC) {
sourceMode = m;
queue = qd;
actual.onSubscribe(this);
return;
}
}
queue = new SpscLinkedArrayQueue<T>(bufferSize);
actual.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();here
}
@Override
public void onError(Throwable t) {
if (done) {
RxJavaPlugins.onError(t);
return;
}
error = t;
done = true;
schedule();
}
@Override
public void onComplete() {
if (done) {
return;
}
done = true;
schedule();
}
@Override
public void dispose() {
if (!cancelled) {
cancelled = true;
s.dispose();
worker.dispose();
if (getAndIncrement() == 0) {
queue.clear();
}
}
}
@Override
public boolean isDisposed() {
return cancelled;
}
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
}
所以什么是rxjava呢,这种响应式的编程,在其间使用装饰模式的概念,创建了一个又一个的ObservableXXX类来实现具体的被观察者,将数据层层包裹处理,又利用了观察者模式的思路实现了多个被观察者对观察者数据发送,,一环扣一环
观察者模式与发布订阅模式
装饰模型
全剧终....