史上最浅显易懂的rxjava入门教程

     2022-04-01     552

关键词:

RxJava是一个神奇的框架,用法很简单,但内部实现有点复杂,代码逻辑有点绕。我读源码时,确实有点似懂非懂的感觉。网上关于RxJava源码分析的文章,源码贴了一大堆,代码逻辑绕来绕去的,让人看得云里雾里的。既然用拆轮子的方式来分析源码比较难啃,不如换种方式,以造轮子的方式,将源码中与性能、兼容性、扩展性有关的代码剔除,留下核心代码带大家揭秘 RxJava 的实现原理。

什么是RxJava

将上面的例子进行代码抽象,步骤如下:

    1. 提供观察者(因为你是关心杂志内容的人 所以你是观察该事件的人)
    1. 提供被观察者(只要有新的杂志出来 就需要通知关心的人 所以报社是被观察的对象)
    1. 订阅(也就是 观察者&被观察者之间要相互关联 以便被观察的对象一变化 就会马上通知观察该事件的对象)

技术图片
上面示例的演示代码如下:
//1.创建被观察者
Observable<String> observable =
Observable.create(new Observable.OnSubscribe<String>() {
br/>@Override
public void call(Subscriber<? super String> subscriber) {
//4.开始发送事件
//事件有3个类型 分别是onNext() onCompleted() onError()
//onCompleted() onError() 一般都是用来通知观察者 事件发送完毕了,两者只取其一。
subscriber.onNext("Hello Android !");
subscriber.onNext("Hello Java !");
subscriber.onNext("Hello C !");
subscriber.onCompleted();
}
});

//2.创建观察者
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onCompleted() {
        Log.i(TAG, "onCompleted ");
    }

    @Override
    public void onError(Throwable e) {
        Log.i(TAG, "onError: "+e.getLocalizedMessage());
    }

    @Override
    public void onNext(String s) {
        Log.i(TAG, "onNext: "+s);
    }
};

//3.订阅
observable.subscribe(subscriber);

输出如下:
com.m520it.rxjava I/IT520: onNext: Hello Android !
com.m520it.rxjava I/IT520: onNext: Hello Java !
com.m520it.rxjava I/IT520: onNext: Hello C !
com.m520it.rxjava I/IT520: onCompleted
代码运行的原理

不知道大家注意到没有,subscribe()订阅的不再是观察者,而是特定的onNext接口对象。类似的函数如下,我们可以根据需要实现对应的订阅:

public Subscription subscribe(final Observer observer)
public Subscription subscribe(final Action1 onNext)
public Subscription subscribe(final Action1 onNext, Action1 onError)
public Subscription subscribe(final Action1 onNext, Action1 onError, Action0 onCompleted)

这里还有一个forEach函数有类似的功能:

public void forEach(final Action1 onNext)
public void forEach(final Action1 onNext, Action1 onError)
public void forEach(final Action1 onNext, Action1 onError, Action0 onComplete)

##7.Subject变种

上面2节中既介绍了被观察者变种,又介绍了观察者变种,这里再介绍一种雌雄同体的对象(既作为被观察者使用,也可以作为观察者)。

针对不同的场景一共有四种类型的Subject。他们并不是在所有的实现中全部都存在。

###AsyncSubject

一个AsyncSubject只在原始Observable完成后,发射来自原始Observable的最后一个值。它会把这最后一个值发射给任何后续的观察者。

以下贴出代码:
//创建被观察者final AsyncSubject<String> subject = AsyncSubject.create();//创建观察者
Subscriber<String> subscriber = new Subscriber<String>() {
br/>@Override
public void onCompleted() {
Log.i(TAG, "onCompleted");
}

@Override
public void onError(Throwable e) {
    Log.i(TAG, "onError");
}

@Override
public void onNext(String s) {
    Log.i(TAG, "s:" + s);

}

};//订阅事件
subject.subscribe(subscriber);//被观察者发出事件 如果调用onCompleted(),onNext()则会打印最后一个事件;如果没有,onNext()则不打印任何事件。
subject.onNext("Hello Android ");
subject.onNext("Hello Java ");
subject.onCompleted();
输出:
s:Hello Java onCompleted
然而,如果原始的Observable因为发生了错误而终止,AsyncSubject将不会发射任何数据,只是简单的向前传递这个错误通知。

上面的观察者被观察者代码相同,现在发出一系列信号,并在最后发出异常 代码如下:

subject.onNext("Hello Android ");
subject.onNext("Hello Java ");//因为发送了异常 所以onNext()无法被打印
subject.onError(null);
###BehaviorSubject

当观察者订阅BehaviorSubject时,他会将订阅前最后一次发送的事件和订阅后的所有发送事件都打印出来,如果订阅前无发送事件,则会默认接收构造器create(T)里面的对象和订阅后的所有事件,代码如下:
BehaviorSubject subject=BehaviorSubject.create("NROMAL");

Subscriber subscriber = new Subscriber() {br/>@Override
public void onCompleted() {
Log.i(TAG, "onCompleted");
}

@Override
public void onError(Throwable e) {
    Log.i(TAG, "onError");
}

@Override
public void onNext(Object o) {
    Log.i(TAG, "onNext: " + o);
}

};
//subject.onNext("Hello Android !");//subject.onNext("Hello Java !");//subject.onNext("Hello C !");//这里开始订阅 如果上面的3个注释没去掉,则Hello C的事件和订阅后面的事件生效//如果上面的三个注释去掉 则打印构造器NORMAL事件生效后和订阅后面的事件生效
subject.subscribe(subscriber);

subject.onNext("Hello CPP !");
subject.onNext("Hello IOS !");
PublishSubject

PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。

需要注意的是,PublishSubject可能会一创建完成就立刻开始发射数据,因此这里有一个风险:在Subject被创建后到有观察者订阅它之前这个时间段内,一个或多个数据可能会丢失。

代码如下:
PublishSubject subject= PublishSubject.create();

Action1<String> onNextAction1 = new Action1<String>(){

@Override
public void call(String s) {
    Log.i(TAG, "onNextAction1 call: "+s);
}

};

Action1<String> onNextAction2 = new Action1<String>(){

@Override
public void call(String s) {
    Log.i(TAG, "onNextAction2 call: "+s);
}

};

subject.onNext("Hello Android !");
subject.subscribe(onNextAction1);
subject.onNext("Hello Java !");
subject.subscribe(onNextAction2);
subject.onNext("Hello IOS !");

输出如下:

onNextAction1 call: Hello Java !
onNextAction1 call: Hello IOS !
onNextAction2 call: Hello IOS !
ReplaySubject

ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。

代码如下:

ReplaySubject subject= ReplaySubject.create();

Action1<String> onNextAction1 = new Action1<String>(){

@Override
public void call(String s) {
    Log.i(TAG, "onNextAction1 call: "+s);
}

};

Action1<String> onNextAction2 = new Action1<String>(){

@Override
public void call(String s) {
    Log.i(TAG, "onNextAction2 call: "+s);
}

};

subject.onNext("Hello Android !");
subject.subscribe(onNextAction1);
subject.onNext("Hello Java !");
subject.subscribe(onNextAction2);
subject.onNext("Hello IOS !");

输出如下:

onNextAction1 call: Hello Android !
onNextAction1 call: Hello Java !
onNextAction2 call: Hello Android !
onNextAction2 call: Hello Java !
onNextAction1 call: Hello IOS !
onNextAction2 call: Hello IOS !
###Subject总结

AsyncSubject无论何时订阅 只会接收最后一次onNext()事件,如果最后出现异常,则不会打印任何onNext()
BehaviorSubject会从订阅前最后一次oNext()开始打印直至结束。如果订阅前无调用onNext(),则调用默认creat(T)传入的对象。如果异常后才调用,则不打印onNext()
PublishSubject只会打印订阅后的任何事件。
ReplaySubject无论订阅在何时都会调用发送的事件。














scala成长之路函数进阶——可能是史上最浅显易懂的闭包教程

由于scala中函数内部能定义函数,且函数能作为函数的返回值,那么问题来了,当返回的函数使用了外层函数的局部变量时,会发生什么呢?没错,就产生是闭包。关于闭包的解释网上一大堆,但基本上都是照葫芦画瓢,一个模... 查看详情

git学习之简介

 一.前言 史上最浅显易懂的Git教程!为什么要编写这个教程?因为我在学习Git的过程中,买过书,也在网上Google了一堆Git相关的文章和教程,但令人失望的是,这些教程不是难得令人发指,就是简单得一笔带过,或者,... 查看详情

微软大神闭关7天整理!477页python学习笔记,极致经典,堪称史上最浅显易懂python入门教程(代码片段)

Python作为当下最热门的编程语言之一,从前几年一直火到现在,并且还有更甚的趋势。不仅吸引了众多业内人士,圈外人士也纷纷加入了学习Python的阵营之中。但很多朋友在学习Python时,直呼:太难了,学... 查看详情

史上最通俗易懂的python入门教程,漫画图文生动有趣,一看就会(代码片段)

全网最简单易懂!495页Python漫画教程,高清PDF版开发下载。今天给那些在学习Python路上有挫折的朋友分享一份《看漫画学Python》,不同的是本书采用漫画的形式,用简单易懂的语言和图片详细解读了Python的每一个知识点。【... 查看详情

git教程

--fast-version-control史上最浅显易懂的Git教程!为什么要编写这个教程?因为我在学习Git的过程中,买过书,也在网上Google了一堆Git相关的文章和教程,但令人失望的是,这些教程不是难得令人发指,就是简单得一笔带过,或者,... 查看详情

史上最通俗易懂的python入门教程,漫画图文生动有趣,一看就会(代码片段)

今天给那些在学习Python路上有挫折的朋友分享一份《看漫画学Python》,不同的是本书采用漫画的形式,用简单易懂的语言和图片详细解读了Python的每一个知识点。【文末免费自取PDF】文档目录数字类型的数据函数常用的内置模块访... 查看详情

git图文教程

号称史上最浅显易懂的Git教程!!! 原文出处: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/ 查看详情

android史上最简单易懂的跨进程通讯(messenger)!

不需要AIDL也不需要复杂的ContentProvider,也不需要SharedPreferences或者共享存储文件!只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递message对象,在message中放入我们需要传递的数据你就可以实现跨进程通讯... 查看详情

windows下git使用入门

铁锚的CSDN的博客http://blog.csdn.net/renfufei/article/details/41647773 史上最浅显易懂的Git教程!https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 查看详情

史上最通俗易懂的理解云计算

“云计算”这三个字相信你一定听过无数遍了,那么我想问问你,“云计算”到底是什么?你能回答出来吗?首先我们听到云计算三个字时,感觉非常高大上,高不可测的,新技术等等,如果你没有接触过的,感觉离我们很远,... 查看详情

史上最通俗易懂的理解云计算

“云计算”这三个字相信你一定听过无数遍了,那么我想问问你,“云计算”到底是什么?你能回答出来吗?首先我们听到云计算三个字时,感觉非常高大上,高不可测的,新技术等等,如果你没有接触过的,感觉离我们很远,... 查看详情

史上最通俗易懂!一文明白git是干嘛的

git的最基本作用是版本控制,比如你写一个文档,老板一直让你改,这时笨的人会在原文档上直接改,聪明一点的会复制一下原文档,在副本上修改,这时老板说你的第三版比较好,笨的人煞笔了。。&... 查看详情

史上最通俗易懂!一文明白git是干嘛的

git的最基本作用是版本控制,比如你写一个文档,老板一直让你改,这时笨的人会在原文档上直接改,聪明一点的会复制一下原文档,在副本上修改,这时老板说你的第三版比较好,笨的人煞笔了。。&... 查看详情

史上最通俗易懂的异或运算详解含例题及应用(代码片段)

一.什么是异或?1.Wikipedia的解释:在逻辑学中,逻辑算符异或(exclusiveor)是对两个运算元的一种逻辑析取类型,符号为XOR或EOR或⊕(编程语言中常用^)。但与一般的逻辑或不同,异或算符的值... 查看详情

网络编程懒人入门:史上最通俗的集线器交换机路由器功能原理入门

1、前言即时通讯网整理了大量的网络编程类基础文章和资料,包括《TCP/IP协议卷1》、《[通俗易懂]深入理解TCP协议》系列、《网络编程懒人入门》系列、《不为人知的网络编程》系列、《P2P技术详解》系列、《高性能网络编程... 查看详情

python爬虫入门到实战-史上最详细的爬虫教程

马哥高薪实战学员【Python爬虫入门到实战-史上最详细的爬虫教程,限时免费领取】爬虫分类和ROBOTS协议爬虫URLLIB使用和进阶爬虫URL编码和GETPOST请求 查看详情

python爬虫入门到实战-史上最详细的爬虫教程

马哥高薪实战学员【Python爬虫入门到实战-史上最详细的爬虫教程,限时免费领取】爬虫分类和ROBOTS协议爬虫URLLIB使用和进阶爬虫URL编码和GETPOST请求 查看详情

史上最详细的sqlmap使用教程(代码片段)

史上最详细的sqlmap使用教程1.sqlmap简介2.初级扫描方案探测是否存在sql注入漏洞查看数据库信息3.高级扫描方案绕过waf探测等级和危险等级(—level—risk)伪造HttpReferer头部执行指定的SQL语句(—sql-shell)执行操作系统命令(—os-shell)读... 查看详情