RxAndroid 入门笔记

article/2025/9/29 22:27:59

参考链接:
http://gank.io/post/560e15be2dca930e00da1083#toc_10
https://mcxiaoke.gitbooks.io/rxdocs/content/Observables.html
http://blog.chengyunfeng.com/?p=948
http://www.apkbus.com/blog-705730-62567.html

要了解RxAndroid,必须先要了解RxJava,应为RxAndroid是RxJava的一个重要的部分。

RxJava介绍

RxJava尽力做到非常轻巧。它仅关注Observable的抽象和与之相关的高层函数,实现为一个单独的JAR文件。

RxJava的github地址:https://github.com/ReactiveX/RxJava
RxAndroid的github地址:https://github.com/ReactiveX/RxAndroid

在RxJava中,一个实现了Observer接口的对象可以订阅(subscribe)一个Observable 类的实例。订阅者(subscriber)对Observable发射(emit)的任何数据或数据序列作出响应。这种模式简化了并发操作,因为它不需要阻塞等待Observable发射数据,而是创建了一个处于待命状态的观察者哨兵,哨兵在未来某个时刻响应Observable的通知。

Observable

observable(可观察者,被观察者),它决定什么时候触发事件以及触发怎样的事件。RxJava使用create()方法创建一个observable,并为它定义事件触发规则。

Observer

observer(观察者),它决定事件触发的时候将有怎样的行为。
回调方法(onNext,onComplete,onError)
onNext:
observable调用这个方法发射数据,方法的参数就是observable发射的数据,这个方法可能会被调用多次,取决于你的实现。
onComplete:
正常终止,如果没有遇到错误,observable在最后一次调用onNext之后调用此方法。
onError:
当observable遇到错误或无法返回期望的数据时会调用这个方法,这个调用会终止Observable,后续不会再调用onNext和onComplete,onError方法的参数是抛出的异常。

Subscriber

Subscriber 是 Observer 的一个实现。

Subscribe

订阅,将观察者和被观察者连接起来的方法。

关系图
这里写图片描述

操作符

  • 用于创建Observable的操作符

Create — 通过调用观察者的方法从头创建一个Observable
Defer — 在观察者订阅之前不创建这个Observable,为每一个观察者创建一个新的Observable
Empty/Never/Throw — 创建行为受限的特殊Observable
From — 将其它的对象或数据结构转换为Observable
Interval — 创建一个定时发射整数序列的Observable
Just — 将对象或者对象集合转换为一个会发射这些对象的Observable
Range — 创建发射指定范围的整数序列的Observable
Repeat — 创建重复发射特定的数据或数据序列的Observable
Start — 创建发射一个函数的返回值的Observable
Timer — 创建在一个指定的延迟之后发射单个数据的Observable

  • 变换操作

这些操作符可用于对Observable发射的数据进行变换,详细解释可以看每个操作符的文档

Buffer — 缓存,可以简单的理解为缓存,它定期从Observable收集数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个
FlatMap — 扁平映射,将Observable发射的数据变换为Observables集合,然后将这些Observable发射的数据平坦化的放进一个单独的Observable,可以认为是一个将嵌套的数据结构展开的过程。
GroupBy — 分组,将原来的Observable分拆为Observable集合,将原始Observable发射的数据按Key分组,每一个Observable发射一组不同的数据
Map — 映射,通过对序列的每一项都应用一个函数变换Observable发射的数据,实质是对序列中的每一项执行一个函数,函数的参数就是这个数据项
Scan — 扫描,对Observable发射的每一项数据应用一个函数,然后按顺序依次发射这些值
Window — 窗口,定期将来自Observable的数据分拆成一些Observable窗口,然后发射这些窗口,而不是每次发射一项。类似于Buffer,但Buffer发射的是数据,Window发射的是Observable,每一个Observable发射原始Observable的数据的一个子集

  • 过滤操作

这些操作符用于从Observable发射的数据中进行选择

Debounce — 只有在空闲了一段时间后才发射数据,通俗的说,就是如果一段时间没有操作,就执行一次操作
Distinct — 去重,过滤掉重复数据项
ElementAt — 取值,取特定位置的数据项
Filter — 过滤,过滤掉没有通过谓词测试的数据项,只发射通过测试的
First — 首项,只发射满足条件的第一条数据
IgnoreElements — 忽略所有的数据,只保留终止通知(onError或onCompleted)
Last — 末项,只发射最后一条数据
Sample — 取样,定期发射最新的数据,等于是数据抽样,有的实现里叫ThrottleFirst
Skip — 跳过前面的若干项数据
SkipLast — 跳过后面的若干项数据
Take — 只保留前面的若干项数据
TakeLast — 只保留后面的若干项数据

  • 组合操作

组合操作符用于将多个Observable组合成一个单一的Observable

And/Then/When — 通过模式(And条件)和计划(Then次序)组合两个或多个Observable发射的数据集
CombineLatest — 当两个Observables中的任何一个发射了一个数据时,通过一个指定的函数组合每个Observable发射的最新数据(一共两个数据),然后发射这个函数的结果
Join — 无论何时,如果一个Observable发射了一个数据项,只要在另一个Observable发射的数据项定义的时间窗口内,就将两个Observable发射的数据合并发射
Merge — 将两个Observable发射的数据组合并成一个
StartWith — 在发射原来的Observable的数据序列之前,先发射一个指定的数据序列或数据项
Switch — 将一个发射Observable序列的Observable转换为这样一个Observable:它逐个发射那些Observable最近发射的数据
Zip — 打包,使用一个指定的函数将多个Observable发射的数据组合在一起,然后将这个函数的结果作为单项数据发射

  • 错误处理

这些操作符用于从错误通知中恢复

Catch — 捕获,继续序列操作,将错误替换为正常的数据,从onError通知中恢复
Retry — 重试,如果Observable发射了一个错误通知,重新订阅它,期待它正常终止

  • 辅助操作

一组用于处理Observable的操作符

Delay — 延迟一段时间发射结果数据
Do — 注册一个动作占用一些Observable的生命周期事件,相当于Mock某个操作
Materialize/Dematerialize — 将发射的数据和通知都当做数据发射,或者反过来
ObserveOn — 指定观察者观察Observable的调度程序(工作线程)
Serialize — 强制Observable按次序发射数据并且功能是有效的
Subscribe — 收到Observable发射的数据和通知后执行的操作
SubscribeOn — 指定Observable应该在哪个调度程序上执行
TimeInterval — 将一个Observable转换为发射两个数据之间所耗费时间的Observable
Timeout — 添加超时机制,如果过了指定的一段时间没有发射数据,就发射一个错误通知
Timestamp — 给Observable发射的每个数据项添加一个时间戳
Using — 创建一个只在Observable的生命周期内存在的一次性资源

  • 条件和布尔操作

这些操作符可用于单个或多个数据项,也可用于Observable

All — 判断Observable发射的所有的数据项是否都满足某个条件
Amb — 给定多个Observable,只让第一个发射数据的Observable发射全部数据
Contains — 判断Observable是否会发射一个指定的数据项
DefaultIfEmpty — 发射来自原始Observable的数据,如果原始Observable没有发射数据,就发射一个默认数据
SequenceEqual — 判断两个Observable是否按相同的数据序列
SkipUntil — 丢弃原始Observable发射的数据,直到第二个Observable发射了一个数据,然后发射原始Observable的剩余数据
SkipWhile — 丢弃原始Observable发射的数据,直到一个特定的条件为假,然后发射原始Observable剩余的数据
TakeUntil — 发射来自原始Observable的数据,直到第二个Observable发射了一个数据或一个通知
TakeWhile — 发射原始Observable的数据,直到一个特定的条件为真,然后跳过剩余的数据

  • 算术和聚合操作

这些操作符可用于整个数据序列

Average — 计算Observable发射的数据序列的平均值,然后发射这个结果
Concat — 不交错的连接多个Observable的数据
Count — 计算Observable发射的数据个数,然后发射这个结果
Max — 计算并发射数据序列的最大值
Min — 计算并发射数据序列的最小值
Reduce — 按顺序对数据序列的每一个应用某个函数,然后返回这个值
Sum — 计算并发射数据序列的和

  • 连接操作

一些有精确可控的订阅行为的特殊Observable

Connect — 指示一个可连接的Observable开始发射数据给订阅者
Publish — 将一个普通的Observable转换为可连接的
RefCount — 使一个可连接的Observable表现得像一个普通的Observable
Replay — 确保所有的观察者收到同样的数据序列,即使他们在Observable开始发射数据之后才订阅

  • 转换操作

To — 将Observable转换为其它的对象或数据结构
Blocking 阻塞Observable的操作符

还有一些其他的操作符:

Convert 转换操作 - ToFuture/ToList/ToIterable/ToMap/toMultiMap
Blocking 阻塞操作 - ForEach/First/Last/MostRecent/Next/Single/Latest
String 字符串操作 - ByLine/Decode/Encode/From/Join/Split/StringConcat
Async 异步操作 - Start/ToAsync/StartFuture/FromAction/FromCallable/RunAsync

Scheduler

RxJava的调度器(Schedulers)为实际生产提供了5中解决方案,如果需要大量IO操作,可以选择Schedulers.io()调度器,如果需要进行密集计算,可以选择Schedulers.computation(),如果只是想开一个线程做些事,可以选择Schedulers.newThread(),借助于RxAndroid,我们还可以使用AndroidSchedulers.mainThread()这个调度器将线程切换回主线程,选择了调度器后,使用一些方法可以将线程切换至调度器对应的线程中。

subscribeOn()和observeOn()

  • observeOn() 指定的是它之后的操作所在的线程。因此如果有多次切换线程的需求,只要在每个想要切换线程的位置调用一次 observeOn() 即可。
    原理图:
    这里写图片描述
  • subscribeOn() 的线程切换发生在 OnSubscribe 中,即在它通知上一级 OnSubscribe 时,这时事件还没有开始发送,因此 subscribeOn() 的线程控制可以从事件发出的开端就造成影响。
    原理图:
    这里写图片描述
Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定.subscribeOn(Schedulers.io()).observeOn(Schedulers.newThread()).map(mapOperator) // 新线程,由 observeOn() 指定.observeOn(Schedulers.io()).map(mapOperator2) // IO 线程,由 observeOn() 指定.observeOn(AndroidSchedulers.mainThread) .subscribe(subscriber);  // Android 主线程,由 observeOn() 指定

不同于 observeOn() , subscribeOn() 的位置放在哪里都可以,但它是只能调用一次的。

当observeOn()和subscribeOn()同时存在时,数据源和操作流程会先处于subscribeOn()所在的线程,直到调用了observeOn()后,线程会切换至observeOn()所在的线程。

如果同时存在多个observeOn()和多个subscribeOn()会怎么样?多个observeOn()好理解,反正什么时候调用到了observeOn(),什么时候就切换线程。而多个subscribeOn()则不同,它们不会被覆盖,只有第一个subscribeOn()线程有效。

总结

create() , just() , from() 等 —-> 事件产生
map() , flapMap() , scan() , filter() 等 —-> 事件加工
subscribe() —-> 事件消费

事件产生:默认运行在当前线程,可以由 subscribeOn() 自定义线程
事件加工:默认跟事件产生的线程保持一致, 可以由 observeOn() 自定义线程
事件消费:默认运行在当前线程,可以有observeOn() 自定义

subscribeOn 用来指定 Observable.create 中的代码在那个 Scheduler 中执行。即使你没有调用 create 函数,但是内部也有一个 create 实现。
observeOn 只影响调用该函数以后的操作函数。你可以认为 observeOn 只是拦截了数据流并且对后续的操作有作用。

doOnSubscribe()

与 Subscriber.onStart() 相对应的,有一个方法 Observable.doOnSubscribe() 。它和 Subscriber.onStart() 同样是在 subscribe() 调用后而且在事件发送前执行,但区别在于它可以指定线程。默认情况下, doOnSubscribe() 执行在 subscribe() 发生的线程;而如果在 doOnSubscribe() 之后有 subscribeOn() 的话,它将执行在离它最近的 subscribeOn() 所指定的线程。

RxJava中ActionX与FuncX的区别

RxJava有一系列的(Func+数字)的接口和一系列(Action+数字)接口,这些接口中都只有一个call方法,其中(Func+数字)接口的call方法都有返回值,而(Action+数字)接口的call方法都没有返回值,后面的那个数字表示call方法接受几个泛型类型的参数。Func1和Action1的源码:

/*** Represents a function with one argument.*/
public interface Func1<T, R> extends Function {R call(T t);
}/*** A one-argument action.*/
public interface Action1<T> extends Action {void call(T t);
}

ActionX用在.subscribe()中的,传入的个数和位置决定用处。ActionX的返回值都为void。
Action1 和 Action0。 Action0 是 RxJava 的一个接口,它只有一个方法 call(),这个方法是无参无返回值的;由于 onCompleted() 方法也是无参无返回值的,因此 Action0 可以被当成一个包装对象,将 onCompleted() 的内容打包起来将自己作为一个参数传入 subscribe() 以实现不完整定义的回调。这样其实也可以看做将 onCompleted() 方法作为参数传进了subscribe(),相当于其他某些语言中的『闭包』。 Action1 也是一个接口,它同样只有一个方法 call(T param),这个方法也无返回值,但有一个参数;与 Action0 同理,由于 onNext(T obj) 和 onError(Throwable error) 也是单参数无返回值的,因此 Action1可以将 onNext(obj) 和 onError(error) 打包起来传入 subscribe() 以实现不完整定义的回调。事实上,虽然 Action0 和 Action1在 API 中使用最广泛,但 RxJava 是提供了多个 ActionX 形式的接口 (例如 Action2, Action3) 的,它们可以被用以包装不同的无返回值的方法。

FuncX常用在map、flatMap中,将传过来的数值类型转化为另一种数值类型,“FuncX”中的“X”代表着多少个参数。
Func1 的类。它和 Action1 非常相似,也是 RxJava 的一个接口,用于包装含有一个参数的方法。 Func1 和Action 的区别在于, Func1 包装的是有返回值的方法。另外,和 ActionX 一样, FuncX 也有多个,用于不同参数个数的方法。FuncX和 ActionX 的区别在 FuncX 包装的是有返回值的方法。


http://chatgpt.dhexx.cn/article/Ox49J7jN.shtml

相关文章

【Rxandroid】Rxandroid源码解读

目录 1.AndroidSchedulers类的源码 2.RxAndroidPlugins类的源码 3.RxAndroidSechedulersHook类的源码 4.LooperScheduler类的源码 5.HandlerScheduler类的源码 6.BuildConfig类的源码 7.MainThreadSubscription类的源码 总结 将Rxandroid&#xff08;1.2.1&#xff09;…

Retrofit + RxAndroid 实践总结

在接入 Retrofit RxAndroid 之前&#xff0c;项目代码中主要存在如下问题&#xff1a; 服务器 API 的定义方式不一致&#xff0c;有的集中定义&#xff0c;有的定义在业务代码中&#xff0c;没有分类不便于维护。Request / Response / API 三者没有对应关系&#xff08;Reque…

Rxjava3 RxAndroid

文章目录 Rxjava && Rxandroid引用方式 概念流程图代码示例ObservableObservable#subscribeOn(NonNull Scheduler scheduler)Observable#observeOn(NonNull Scheduler scheduler)ObservableSubscribeOnObservableObserveOn本文开头的代码示例等同于如下代码 Schedulers…

RxJava和RxAndroid学习记录

目录 1 概念和说明 1.1 响应式编程 1.2 RxJava 1.3 关于RxJava和RxAndroid 1.4 关于响应式编程和普通编程 2. 基本使用 2.1 基本元素关系图 2.2 代码示例&#xff1a; 2.3 关于subscribe&#xff08;&#xff09; 2.4 线程调度 2.4.1 线程调度 2.4.2 RxJava内置的常用…

RxAndroid的基础使用

作为一个android开发者&#xff0c;在开发应用的过程中避免不了异步这个问题。android系统为我们提供了Handler这个类帮助我们进行线程间的通信和切换&#xff0c;但是GitHub上也有很多其他非常优秀的开源框架来帮助我们进行异步处理&#xff0c;比如今天学习的RxAndroid。 简…

rxandroid 基础知识

概述 在Android 中, 使用 rxandroid , rxandroid和rxJava的关系是,rxandroid包 依赖rxJava包,在其功能上增加了一些Android特有功能,项目中如果不需要指定rxJava包的版本,只需引入rxandroid包即可,如果需要更改 rxandroid包中默认的rxJava包版本 , 在项目中引入指定的rxJava包即…

RxAndroid使用初探;简洁、优雅、高效

引言 RxAndroid是一个开发库、是一种代码风格、也是一种思维方式。 正如标题所言,RxAndroid的特点是简洁、优雅、高效,它的优点是多线程切换简单、数据变换容易、代码简洁可读性好、第三方支持丰富易于开发;缺点是学习成本较高、出错难以排查。 用途与优势 起源 RxAndroid…

RxAndroid的学习和研究

1.什么是RxAndroid RxAndroid的含义为响应式编程&#xff0c;Rx含义是响应式编程&#xff0c;其本质就是观察者模式&#xff0c;以观察者&#xff08;Observer&#xff09;和订阅者&#xff08;Subscriber&#xff09;为基础的异步响应方式。    Observables发出一系列事件&a…

linux基本功系列之dd命令实战

文章目录 前言&#x1f680;&#x1f680;&#x1f680;一. dd 命令介绍二. 语法格式及常用选项三. 参考案例3.1 创建指定大小的文件3.2 清空磁盘数据3.3 给磁盘做备份还原3.4 把光盘拷贝到root下3.5 内存不足的处理方法 四. 文中出现的概念解释swapon命令介绍4.2 /dev/zero 介…

Linux系统中dd命令用法详解

命令介绍&#xff1a; Linux dd 命令用于读取、转换并输出数据。dd 可从标准输入或文件中读取数据&#xff0c;根据指定的格式来转换数据&#xff0c;再输出到文件、设备或标准输出。 参数介绍 if 代表输入文件。如果不指定 if&#xff0c;默认就会从 stdin 中读取输入。of …

dd 命令详解

dd命令是Linux/Unix下的一个很常见的文件拷贝工具。 我们先列下dd命名的常用的参数&#xff0c;再详细分析&#xff1a; bsBYTES read and write up to BYTES bytes at a time cbsBYTES convert BYTES bytes at a time convCONVS convert the file as pe…

dd命令使用总结

dd命令介绍 dd是Linux下一个非常有用的命令&#xff0c;该命令用于读取、转换并输出数据&#xff1b;dd命令在Android shell下也支持使用。 语法格式&#xff1a; dd [option]dd指令选项详解 iffile&#xff1a;输入文件名&#xff0c;缺省为标准输入 offile&#xff1a;输…

dd命令相关整理

对于一个软件测试人员而言&#xff0c;工作开展前就是准备自己的测试环境&#xff0c;那么重装系统就是首当其冲的一个必备技能。最近因为手边工作环境没有windows的系统&#xff0c;所以没有条件利用软碟通这类刻录软件直接刻录启动盘。被逼无奈之下用命令来刻录&#xff0c;整…

Linux:shell 脚本 自动解压压缩文件tar.gz到指定目录

具体情境 Ubuntu16.04系统&#xff0c;将.tar.gz格式的文件从/home/myftp/upload/nuodongiot目录自动解压到/home/myftp/upload/backupcopy目录中&#xff0c;并将源目录/home/myftp/upload/nuodongiot中的文件移动至/home/myftp/upload/extarct目录中 该过程进行单个文件进行…

tar解压文件至指定目录,不包含原目录

1、tar解压文件至指定目录&#xff0c;不包含原目录 要解压的压缩包原目录结构如下 tar -zxf log.tar.gz --strip-components 1 -C /opt/new_test注&#xff1a; --strip-components 1 解压至下一级目录&#xff0c;若为2则解压至下下级目录 2、压缩只指定的目录&#xff0c…

linux gz解压 指定目,linux解压tar.gz到指定文件夹或目录

1. 前言 本文主要讲解如何解压tar.gz到指定文件夹或目录,tar是Linux系统上的一种打包与压缩工具。 2. linux解压tar文件使用案例 Linux下使用tar命令把当前目录下的zcwyou.tar.gz解压到指定的目录/123/abc/ ,前提要保证存在/123/abc/这个目录。 [root@zcwyou ~]# tar -zxvf zc…

Linux tar 命令 将归档内指定文件解压到指定目录

首先介绍一下 tar 命令&#xff1a; 用途&#xff1a;打包文件&#xff08;制作归档文件&#xff09;、释放归档文件 格式&#xff1a; tar [选项]... 归档文件名 源文件或目录 tar [选项]... 归档文件名 [-C 目标目录] 常用命令选项&#xff1a; -c 创建 .tar 格式…

20191004在LINUX下如何将tar压缩文件解压到指定的目录下

百度搜索&#xff1a;tar 解压缩到指定目录 https://zhidao.baidu.com/question/9844116.html 在LINUX下如何将tar压缩文件解压到指定的目录下 各位&#xff0c;请教一下在LINUX下如何将tar压缩文件解压到指定的目录下&#xff0c;直接用tar xvf 解压出来的是放在当前目录的&am…

关于linux打包以及解压到指定目录的简单操作demo

1.打包到指定目录 命令:tar zcvf /root/test99/a.tar.gz a.txt 1.1打包到当前目录 命令:tar -zcvf a.tar.gz a.txt 2.解压到指定目录 命令: tar -zxvf a.tar.gz -C /root/test99 2.2解压到当前目录 命令:tar -zxvf a.tar.gz 打zip包: 方法如下&#xf…

linux tar解压文件至指定目录,不包含原目录

1、tar解压文件至指定目录&#xff0c;不包含原目录 要解压的压缩包原目录结构如下 通过 --strip-components 1 参数 解压到指定目录或当前目录&#xff08;不含打包前原目录&#xff09; tar zxf log.tar.gz --strip-components 1 -C /opt/new_test注&#xff1a; --strip-co…