RxJava的订阅过程
要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展
implementation 'io.reactivex:rxandroid:1.2.1'implementation 'io.reactivex:rxjava:1.2.0'
首先从最基本的Observable的创建到订阅开始分析
Observable.create(new Observable.OnSubscribe<String>() {@Overridepublic void call(Subscriber<? super String> subscriber) {subscriber.onNext("observable call onNext0");subscriber.onStart();subscriber.onNext("observable call onNext");subscriber.onCompleted();subscriber.onNext("observable call onNext1");}}).subscribe(new Subscriber<String>() {@Overridepublic void onCompleted() {ILog.LogDebug("subscriber onCompleted");}@Overridepublic void onError(Throwable e) {ILog.LogDebug("subscriber onError");}@Overridepublic void onNext(String s) {ILog.LogDebug("subscriber onNext");}});
Observable.create()需要一个OnSubscribe,OnSubscribe又是什么呢
public static <T> Observable<T> create(OnSubscribe<T> f) {return new Observable<T>(RxJavaHooks.onCreate(f));}
OnSubscribe是一个接口,继承自Action1,Action1继承自Action,Action继承自Function,Function就是所有的action和fun的基类,于是有
OnSubscribe > Action1 > Action > Function , 由于Action1 接口有一个call方法,OnSubscribe接口也拥有了一个call方法。call方法的参数是一个Subscriber
/*** Invoked when Observable.subscribe is called.* @param <T> the output value type*/public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {// cover for generics insanity}/*** A one-argument action.* @param <T> the first argument type*/public interface Action1<T> extends Action {void call(T t);}/*** All Action interfaces extend from this.* <p>* Marker interface to allow instanceof checks.*/public interface Action extends Function {}/*** All Func and Action interfaces extend from this.* <p>* Marker interface to allow instanceof checks.*/public interface Function {}
接着继续看RxJavaHooks.onCreate(f)做了什么 , 由于RxJavaHooks 源码较多,这里只贴了关键的一部分,onObservableCreate为RxJavaHooks 初始化后在static区自动执行赋值的,Func1类型,RxJavaHooks.onCreate最后也就是调用了f.call(onSubscribe),参数是我们传进去的onSubscribe实例
public final class RxJavaHooks {........@SuppressWarnings("rawtypes")static volatile Func1<Observable.OnSubscribe, Observable.OnSubscribe> onObservableCreate;@SuppressWarnings("rawtypes")static volatile Func2<Observable, Observable.OnSubscribe, Observable.OnSubscribe> onObservableStart;static volatile Func1<Subscription, Subscription> onObservableReturn;
......../*** Hook to call when an Observable is created.* @param <T> the value type* @param onSubscribe the original OnSubscribe logic* @return the original or replacement OnSubscribe instance*/@SuppressWarnings({ "rawtypes", "unchecked" })public static <T> Observable.OnSubscribe<T> onCreate(Observable.OnSubscribe<T> onSubscribe) {Func1<Observable.OnSubscribe, Observable.OnSubscribe> f = onObservableCreate;if (f != null) {return f.call(onSubscribe);}return onSubscribe;}/*** Hook to call before the Observable.subscribe() method is about to return a Subscription.* @param subscription the original subscription* @return the original or alternative subscription that will be returned*/public static Subscription onObservableReturn(Subscription subscription) {Func1<Subscription, Subscription> f = onObservableReturn;if (f != null) {return f.call(subscription);}return subscription;}/*** Hook to call before the child subscriber is subscribed to the OnSubscribe action.* @param <T> the value type* @param instance the parent Observable instance* @param onSubscribe the original OnSubscribe action* @return the original or alternative action that will be subscribed to*/@SuppressWarnings({ "rawtypes", "unchecked" })public static <T> Observable.OnSubscribe<T> onObservableStart(Observable<T> instance, Observable.OnSubscribe<T> onSubscribe) {Func2<Observable, Observable.OnSubscribe, Observable.OnSubscribe> f = onObservableStart;if (f != null) {return f.call(instance, onSubscribe);}return onSubscribe;}.......@SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })static void initCreate() {onObservableCreate = new Func1<Observable.OnSubscribe, Observable.OnSubscribe>() {@Overridepublic Observable.OnSubscribe call(Observable.OnSubscribe f) {return RxJavaPlugins.getInstance().getObservableExecutionHook().onCreate(f);}};onObservableStart = new Func2<Observable, Observable.OnSubscribe, Observable.OnSubscribe>() {@Overridepublic Observable.OnSubscribe call(Observable t1, Observable.OnSubscribe t2) {return RxJavaPlugins.getInstance().getObservableExecutionHook().onSubscribeStart(t1, t2);}};onObservableReturn = new Func1<Subscription, Subscription>() {@Overridepublic Subscription call(Subscription f) {return RxJavaPlugins.getInstance().getObservableExecutionHook().onSubscribeReturn(f);}};onSingleCreate = new Func1<rx.Single.OnSubscribe, rx.Single.OnSubscribe>() {@Overridepublic rx.Single.OnSubscribe call(rx.Single.OnSubscribe f) {return RxJavaPlugins.getInstance().getSingleExecutionHook().onCreate(f);}};onCompletableCreate = new Func1<Completable.OnSubscribe, Completable.OnSubscribe>() {@Overridepublic Completable.OnSubscribe call(Completable.OnSubscribe f) {return RxJavaPlugins.getInstance().getCompletableExecutionHook().onCreate(f);}};}....}
在 f.call中 又调用了
RxJavaPlugins.getInstance().getObservableExecutionHook().onCreate(f); 最后返回的就是我们传入的onSubscribe
public abstract class RxJavaObservableExecutionHook { ......@Deprecatedpublic <T> OnSubscribe<T> onCreate(OnSubscribe<T> f) {return f;}@Deprecatedpublic <T> OnSubscribe<T> onSubscribeStart(Observable<? extends T> observableInstance, final OnSubscribe<T> onSubscribe) {// pass through by defaultreturn onSubscribe;}@Deprecatedpublic <T> Subscription onSubscribeReturn(Subscription subscription) {// pass through by defaultreturn subscription;}
......
}
最后在回来看new Observable(RxJavaHooks.onCreate(f)), Observable 的构造方法,Observable把传入的onSubscribe 保存了起来。至此饶了一大圈Observable对象产生。
public class Observable<T> {
.....protected Observable(OnSubscribe<T> f) {this.onSubscribe = f;}.....
}
下面会继续调用Observable的subscribe方法并传入Observer(观察者),完成订阅操作。现在来查看Observable的subscribe方法做了什么
public class Observable<T> {
.....public final Subscription subscribe(Subscriber<? super T> subscriber) {return Observable.subscribe(subscriber, this);}
.....static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {// validate and proceedif (subscriber == null) {throw new IllegalArgumentException("subscriber can not be null");}if (observable.onSubscribe == null) { //此处的onSubscribe正是我们创建订阅的时候传入的onSubscribe throw new IllegalStateException("onSubscribe function can not be null.");/** the subscribe function can also be overridden but generally that's not the appropriate approach* so I won't mention that in the exception*/}// new Subscriber so onStart itsubscriber.onStart();/** See https://github.com/ReactiveX/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls* to user code from within an Observer"*/// if not already wrappedif (!(subscriber instanceof SafeSubscriber)) {// assign to `observer` so we return the protected versionsubscriber = new SafeSubscriber<T>(subscriber);}// The code below is exactly the same an unsafeSubscribe but not used because it would// add a significant depth to already huge call stacks.try {// allow the hook to intercept and/or decorateRxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);return RxJavaHooks.onObservableReturn(subscriber);} catch (Throwable e) {// special handling for certain Throwable/Error/Exception typesExceptions.throwIfFatal(e);// in case the subscriber can't listen to exceptions anymoreif (subscriber.isUnsubscribed()) {RxJavaHooks.onError(RxJavaHooks.onObservableError(e));} else {// if an unhandled error occurs executing the onSubscribe we will propagate ittry {subscriber.onError(RxJavaHooks.onObservableError(e));} catch (Throwable e2) {Exceptions.throwIfFatal(e2);// if this happens it means the onError itself failed (perhaps an invalid function implementation)// so we are unable to propagate the error correctly and will just throwRuntimeException r = new OnErrorFailedException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);// TODO could the hook be the cause of the error in the on error handling.RxJavaHooks.onObservableError(r);// TODO why aren't we throwing the hook's return value.throw r; // NOPMD}}return Subscriptions.unsubscribed();}}.....
}
在正式的订阅关系产生之前,首先会执行subscriber.onStart()方法,这里可以做一些初始化工作。继续往下看又判断是subscriber 实例是否是一个SafeSubscriber,不是则会新建一个SafeSubscriber来包装subscriber
if (!(subscriber instanceof SafeSubscriber)) {// assign to `observer` so we return the protected versionsubscriber = new SafeSubscriber<T>(subscriber);}
老规矩,查看SafeSubscriber源码
public class SafeSubscriber<T> extends Subscriber<T> {private final Subscriber<? super T> actual;boolean done;public SafeSubscriber(Subscriber<? super T> actual) {super(actual);this.actual = actual;}/*** Notifies the Subscriber that the {@code Observable} has finished sending push-based notifications.* <p>* The {@code Observable} will not call this method if it calls {@link #onError}.*/@Overridepublic void onCompleted() {if (!done) {done = true;try {actual.onCompleted();} catch (Throwable e) {// we handle here instead of another method so we don't add stacks to the frame// which can prevent it from being able to handle StackOverflowExceptions.throwIfFatal(e);RxJavaHooks.onError(e);throw new OnCompletedFailedException(e.getMessage(), e);} finally { // NOPMDtry {// Similarly to onError if failure occurs in unsubscribe then Rx contract is broken// and we throw an UnsubscribeFailureException.unsubscribe();} catch (Throwable e) {RxJavaHooks.onError(e);throw new UnsubscribeFailedException(e.getMessage(), e);}}}}/*** Notifies the Subscriber that the {@code Observable} has experienced an error condition.* <p>* If the {@code Observable} calls this method, it will not thereafter call {@link #onNext} or* {@link #onCompleted}.** @param e* the exception encountered by the Observable*/@Overridepublic void onError(Throwable e) {// we handle here instead of another method so we don't add stacks to the frame// which can prevent it from being able to handle StackOverflowExceptions.throwIfFatal(e);if (!done) {done = true;_onError(e);}}/*** Provides the Subscriber with a new item to observe.* <p>* The {@code Observable} may call this method 0 or more times.* <p>* The {@code Observable} will not call this method again after it calls either {@link #onCompleted} or* {@link #onError}.** @param args* the item emitted by the Observable*/@Overridepublic void onNext(T args) {try {if (!done) {actual.onNext(args);}} catch (Throwable e) {// we handle here instead of another method so we don't add stacks to the frame// which can prevent it from being able to handle StackOverflowExceptions.throwOrReport(e, this);}}/*** The logic for {@code onError} without the {@code isFinished} check so it can be called from within* {@code onCompleted}.** @see <a href="https://github.com/ReactiveX/RxJava/issues/630">the report of this bug</a>*/protected void _onError(Throwable e) { // NOPMDRxJavaHooks.onError(e);try {actual.onError(e);} catch (OnErrorNotImplementedException e2) { // NOPMD/** onError isn't implemented so throw** https://github.com/ReactiveX/RxJava/issues/198** Rx Design Guidelines 5.2** "when calling the Subscribe method that only has an onNext argument, the OnError behavior* will be to rethrow the exception on the thread that the message comes out from the observable* sequence. The OnCompleted behavior in this case is to do nothing."*/try {unsubscribe();} catch (Throwable unsubscribeException) {RxJavaHooks.onError(unsubscribeException);throw new OnErrorNotImplementedException("Observer.onError not implemented and error while unsubscribing.", new CompositeException(Arrays.asList(e, unsubscribeException))); // NOPMD}throw e2;} catch (Throwable e2) {/** throw since the Rx contract is broken if onError failed** https://github.com/ReactiveX/RxJava/issues/198*/RxJavaHooks.onError(e2);try {unsubscribe();} catch (Throwable unsubscribeException) {RxJavaHooks.onError(unsubscribeException);throw new OnErrorFailedException("Error occurred when trying to propagate error to Observer.onError and during unsubscription.", new CompositeException(Arrays.asList(e, e2, unsubscribeException)));}throw new OnErrorFailedException("Error occurred when trying to propagate error to Observer.onError", new CompositeException(Arrays.asList(e, e2)));}// if we did not throw above we will unsubscribe here, if onError failed then unsubscribe happens in the catchtry {unsubscribe();} catch (Throwable unsubscribeException) {RxJavaHooks.onError(unsubscribeException);throw new OnErrorFailedException(unsubscribeException);}}/*** Returns the {@link Subscriber} underlying this {@code SafeSubscriber}.** @return the {@link Subscriber} that was used to create this {@code SafeSubscriber}*/public Subscriber<? super T> getActual() {return actual;}
}
SafeSubscriber是Subscriber的一个具体实现类,看SafeSubscriber像不像一个代理模式,具体的工作都是由actual来做,SafeSubscriber负责更完善的处理操作。
继续回到订阅部分的代码,类似之前的分析,代码已经在上面类贴出 RxJavaHooks.onObservableStart(observable, observable.onSubscribe)也只是返回了observable.onSubscribe实例,最后的.call(subscriber)也就是直接调用了我们在创建observable时传入的匿名实例call方法,最后返回subscriber。
RxJava的订阅过程就基本分析完了。
相关文章:
RxJava的订阅过程
要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0首先从最基本的Observable的创建到订阅开始分析 Observable.create(new Observable.OnSubscribe<S…...
【2.22】MySQL、Redis、动态规划
认识Redis Redis是一种基于内存的数据库,对数据的读写操作都是在内存中完成的,因此读写速度非常快,常用于缓存,消息队列,分布式锁等场景。 Redis提供了多种数据类型来支持不同的业务场景,比如String(字符串…...
2年手动测试,裸辞后找不到工作怎么办?
我们可以从以下几个方面来具体分析下,想通了,理解透了,才能更好的利用资源提升自己。一、我会什么?先说第一个我会什么?第一反应:我只会功能测试,在之前的4年的中我只做了功能测试。内心存在一种…...
Leetcode6. N字形变换
一、题目描述: 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下: 之后,你的输出需要从左往右逐行读取,产…...
将Nginx 核心知识点扒了个底朝天(十)
ngx_http_upstream_module的作用是什么? ngx_http_upstream_module用于定义可通过fastcgi传递、proxy传递、uwsgi传递、memcached传递和scgi传递指令来引用的服务器组。 什么是C10K问题? C10K问题是指无法同时处理大量客户端(10,000)的网络套接字。 Nginx是否支持将请求压…...
GPU显卡环境配置安装
前言 最近公司购买了一张RTX3090的显卡和一台新的服务器,然后对机器的GPU环境进行了安装和配置,然后简单记录一下 环境版本 操作系统:Centos7.8 显卡型号:RTX3090 Python版本:3.7.6 Tensorflow版本:2…...
CIMCAI super unmanned intelligent gate container damage detect
世界港航人工智能领军者企业CIMCAI中集飞瞳打造全球最先进超级智能闸口无人闸口ceaspectusG™视频流动态感知集装箱箱况残损检测箱况残损识别率99%以上,箱信息识别率99.95%以上World port shipping AI leader CIMCAIThe worlds most advanced super intelligent gat…...
web概念概述
软件架构:1. C/S: Client/Server 客户端/服务器端* 在用户本地有一个客户端程序,在远程有一个服务器端程序* 如:QQ,迅雷...* 优点:1. 用户体验好* 缺点:1. 开发、安装,部署,维护 麻烦…...
编译原理笔记(1)绪论
文章目录1.什么是编译2.编译系统的结构3.词法分析概述4.语法分析概述5.语义分析概述6.中间代码生成和后端概述1.什么是编译 编译的定义:将高级语言翻译成汇编语言或机器语言的过程。前者称为源语言,后者称为目标语言。 高级语言源程序的处理过程&#…...
MySQL(八)
服务器参数设置 general datadir/var/lib/mysql 数据文件存放的目录socket/var/lib/mysql/mysql.sock mysql.socket表示server和client在同一台服务器,并且使用localhost进行连接,就会使用socket进行连接pid_file/var/lib/mysql/mysql.pid 存储mysql的p…...
steam搬砖项目,小投入高回报,可放大操作,(内附教学资料)
我必须要说,steam搬砖项目就是全网门槛最低的副业,有手就行! 本人90后底层员工一枚,新入csgo搬砖项目,轻松翻身 什么做抖音、海外问卷、直播卖货,电商等等对比我这个都是小钱。我这个方法是利用了大部分人…...
华为OD机试真题Python实现【最多提取子串数目】真题+解题思路+代码(20222023)
最多提取子串数目 题目 给定由 [a-z] 26 个英文小写字母组成的字符串 A 和 B,其中 A 中可能存在重复字母,B 中不会存在重复字母 现从字符串 A 中按规则挑选一些字母,可以组成字符串 B。 挑选规则如下: 1) 同一个位置的字母只能被挑选一次 2) 被挑选字母的相对先后顺序不…...
day32 多线程(上)
文章目录相关概念codeThreadTest01ThreadTest02 编写一个类,直接继承java.lang.Thread,重写run方法ThreadTest03 实现线程的第二种方法ThreadTest04 采用匿名内部类的方式ThreadTest05 获取线程名字ThreadTest06 sleep方法sleep面试题ThreadTest08 终止线…...
【flink】 各种join类型对比
表定义 动态表(dynamic table):动态表是流的另一种表达方式,动态表作为一个逻辑的抽象概念,使我们更容易理解flink中将streaming发展到table这个层次的设计,本质都是对无边界、持续变更数据的表示形式,所以动态表与流之…...
常用正则表达式
一、校验数字的表达式 数字:^[0-9]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^\d{m,n}$ 零和非零开头的数字:^(0|[1-9][0-9]*)$ 非零开头的最多带两位小数的数字:^([1-9][0-9]*)(.[0…...
PMP考试有没有什么技巧可以介绍一下么?
一、试题形式 ——中英文对照 即每道题都是一遍英文,一遍翻译的中文,在审题的时候有一些小的技巧需要注意。首先如果你的英文水平足够好,建议直接阅读原文。PMP试题毕竟是美国人出的,语言的组织、思想的表达,肯定更符…...
2022-2023年营销报告(B站平台) | 5大行业势态、流量大盘全景洞察
一直以来,手持高活跃、高粘性用户群体的B站是行业用来观察年轻人消费习惯的重要平台。以至于用户群体的不断壮大带动了B站的商业价值。如今B站的商业舞台越来越大,不断地向外界招手,欢迎更多品牌积极加入到这个千万年轻人聚集的内容社区。为了…...
Python的异常与工具包
异常 当检测到一个错误时,python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的异常。 捕获异常 世界上没有完美的程序,任何程序在运行的过程中,都有可能出现异常,导致程序无法完美运行…...
基于SSM的婴幼儿商城
基于SSM的婴幼儿商城 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: …...
2023年新能源汽车行业研究报告
第一章 行业概况 新能源汽车,是指采用新型动力系统,完全或者主要依靠新型能源驱动的汽车,包括纯电动汽车、插电式混合动力汽车、增程式混合动力汽车和燃料电池汽车等。国际上,混合动力汽车(含中混、强混、插电式混动&…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
