前言
在上一篇中我们了解到:Observable = 可观察序列,负责发射事件。 Observable 本质是一个“事件生产工厂”,它可以发出三类事件:
.next(element):携带业务数据,可以多次发送.error(Error):异常,序列立刻终止,后续不再发送任何事件.completed:正常结束,序列终止,不再发送事件
重点:一旦序列触发 error / completed,这条数据流就终结。
Observable 分为冷、热。本篇我们全部围绕冷序列讲解:没有订阅,就不会执行;每次订阅都会重新独立执行一遍。
一、常见的 Observable 创建方法
RxSwift内置大量构造方法,我们逐个看,附带代码示例。
1. just
只发射单个元素,然后完成。
let observable = Observable.just("Hello Rx") observable.subscribe { event in print(event) }输出:
next(Hello Rx) completed适用场景:包装单个固定值,常量封装。
2. of
依次发射多个元素,然后完成。
let observable = Observable.of(1,2,3) observable.subscribe { event in print(event) }输出:
next(1) next(2) next(3) completed3. from
从数组中逐个取出元素发射。
let observable = Observable.from([10,20,30]) observable.subscribe { event in print(event) }区分:
of([1,2,3])是一次性把数组作为单个next发出;from([1,2,3])遍历数组逐个发射元素。
4. empty
直接发送completed,不发射任何 next。
let observable = Observable<Int>.empty() observable.subscribe { event in print(event) }输出:completed场景:分支逻辑里,返回一个空序列,没有数据,正常结束。
5. never
永不发射任何事件(next/error/completed 都没有)。
let observable = Observable<Int>.never()适合测试,或者代表无限持续的流(极少业务使用)。
6. create
手写自定义Observable(最重要!理解底层)。
create允许我们自己定义什么时候发送 next / error / completed。
所有 Rx内置创建符,底层本质都是基于
create封装。
// 手写一个自定义Observable let myObservable = Observable<String>.create { observer in // 这里:订阅发生时,代码才会执行!【冷序列关键点】 print("✅ 开始生产事件") observer.onNext("第一条消息") observer.onNext("第二条消息") // observer.onError(NSError(domain: "demo", code: -1)) observer.onCompleted() // 返回一个Disposable,订阅销毁时执行 return Disposables.create { print("🗑️ 订阅被释放") } } // 第一次订阅 myObservable.subscribe { event in print("订阅1收到:\(event)") } print("=====分割线=====") // 第二次订阅 myObservable.subscribe { event in print("订阅2收到:\(event)") }运行输出:
✅ 开始生产事件 订阅1收到:next(第一条消息) 订阅1收到:next(第二条消息) 订阅1收到:completed 🗑️ 订阅被释放 =====分割线===== ✅ 开始生产事件 订阅2收到:next(第一条消息) 订阅2收到:next(第二条消息) 订阅2收到:completed 🗑️ 订阅被释放核心结论: 每一次subscribe,都会重新执行 create 内部的生产代码! 这就是冷序列最直观的体现:每个订阅者独立一份数据流。
二、subscribe:
订阅,连接 Observable 和 Observer。
subscribe有多个重载方法,从完整回调到简写形式。
1.完整事件回调
observable.subscribe { event in switch event { case .next(let value): print("next: \(value)") case .error(let err): print("error: \(err)") case .completed: print("completed") } }2.拆分四个单独闭包
observable.subscribe( onNext: { value in print("onNext: \(value)") }, onError: { error in print("onError: \(error)") }, onCompleted: { print("onCompleted") }, onDisposed: { print("onDisposed:订阅销毁") } )- onNext:接收正常数据
- onError:接收错误,收到error后序列终止,不会再触发onNext/onCompleted
- onCompleted:正常结束
- onDisposed:无论正常完成、报错、手动取消,最终都会执行,做资源清理。
坑提醒:
onError一旦触发,onCompleted永远不会执行,二选一。
三、Disposable & DisposeBag,Rx内存管理核心
1. Disposable
调用subscribe的返回值就是Disposable,代表这次订阅资源。 你可以手动调用.dispose()提前终止数据流:
let disposable = Observable.of(1,2,3).subscribe(onNext: { print($0) }) disposable.dispose() // 手动取消订阅但是项目里极少手动调用 dispose(),太容易遗漏。
2. DisposeBag(销毁袋)
DisposeBag 相当于订阅的容器。
把 disposabledisposed(by: bag)添加进去。 当 DisposeBag 实例被释放(如ViewController销毁),会自动批量调用所有订阅的 dispose。
class DemoVC: UIViewController { // 定义销毁包,页面生命周期持有 private let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() Observable.of("A","B","C") .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) // 加入销毁袋 } }黄金规则:所有订阅,必须交给 DisposeBag 管理。 如果不加入disposeBag,对于无限序列(比如持续的UI输入流)会造成内存泄漏,页面pop之后订阅继续存活。
⚠️ 重要误区: ✅ 一个ViewController只需要一个disposeBag(常规场景) ❌ 不要每次订阅都新建DisposeBag
四、实战Demo:验证冷序列特性
我们用create的例子验证,多次订阅会多次执行内部逻辑:
let obs = Observable<Int>.create { observer in print("开始执行序列逻辑") observer.onNext(1) observer.onCompleted() return Disposables.create() } print("准备第一次订阅") obs.subscribe(onNext: { print("sub1: \($0)") }) print("准备第二次订阅") obs.subscribe(onNext: { print("sub2: \($0)") })输出:
准备第一次订阅 开始执行序列逻辑 sub1: 1 准备第二次订阅 开始执行序列逻辑 sub2: 1两次订阅,两次打印开始执行序列逻辑。
这就是网络请求包装成Observable之后,每次订阅都会重新发起网络请求的底层原因!这个知识点面试高频。
五、常见新手坑总结
- ❌ 误以为Observable创建时就开始执行事件 ✅ 只有subscribe订阅之后,才会执行生产逻辑(冷序列)
- ❌ 忘记把订阅加入disposeBag,无限流造成内存泄漏 ✅ 任何长期存在的数据流,都要
disposed(by: disposeBag) - ❌ 认为error和completed可以同时触发 ✅ error / completed 互斥,任意一个发出,序列终结
- ❌ 混淆
of([1,2,3])和from([1,2,3])✅ of传数组会把整个数组作为单个next;from会逐个遍历元素发射
本篇小结
- Observable 发射三类事件:next、error、completed;error/completed会终止序列。
- 常用创建符:just / of / from / empty / never;
create是自定义底层API。 - subscribe 建立订阅连接,冷序列在订阅那一刻才开始执行。
- Disposable 代表订阅资源;DisposeBag自动批量销毁订阅,是Rx内存管理基石。
- 冷序列:每一次订阅,独立从头执行(网络请求Observable就是典型)。
思考题
- 如果Observable发送了onError,onDisposed会不会执行?
- 我们用Moya封装的网络请求Observable,是冷信号还是热信号?多次订阅会发生什么?
- empty 和 never 的核心区别是什么,各自适用场景?