前言
就我学习RxSwift的感觉,各种文档和说明都会说Observable是Rx中最最最核心的部分。
然而,正是因为它核心、关键,理解起来也不容易。编程本来就是非常抽象的事情,又想把抽象中的知识点梳理清楚亦是困难。
最近上了公司的一节培训课,说真正的大佬,对于非常深奥的问题和概念,总能一语中的,通俗易懂的说明白。
针对Observable我也一直在思考,如何给大家解释清楚,吃饭和睡觉都在想这事。
下面就给大家带来我的理解。
先解释一下Observable这个单词
大家注意它是一个形容词,意思是可观察得到的。
官方中文文档的解释是:可被观察的序列(Observable)。
由于名字过长,很多时候会增加阅读难度,所以必要时会将它简写为:序列。
序列,这个词是不是特别熟悉?英文是sequence,是不是想起了什么?没错,Swift中有一个Sequence
协议。
Sequence
是一系列相同类型的值的集合,并且提供对这些值得迭代能力,迭代一个Sequence最常见的方式就是for-in,并且提供对这些值得迭代能力。
想必这段代码大家都很熟悉:
for element in someSequence {
print(element)
}
for-in是一种语法糖,只要一个class或者struct遵守Sequence协议都可以做这个语法迭代,而更为关键是Sequence
协议中的IteratorProtocol
协议,正是有它,才能去遍历到下一个元素。
上面说了这么多,从Observable到序列,然后又到Sequence协议,是不是觉得很茫然?
茫然是正常的,因为Sequence、IteratorProtocol这些协议非常抽象,不便于理解,而遵守Sequence协议的类型我们倒是非常熟悉——数组Array。
下面就让我们通过类比Array,来理解Observable。
Array与Observable
我们先来一段数组的forEach遍历:
let array = [0, 1, 2, 3, 4, 5]
array.forEach { element in
print(element)
}
打印的结果大家也非常熟悉:
0
1
2
3
4
5
然后我们来生成一个Observable也来干这件事情。
let element = [0, 1, 2, 3, 4, 5]
let observable = Observable.from(element)
observable.subscribe { event in
print(event)
}.dispose()
当你在使用
Observable
时,如果能够直接将其他类型转换为Observable
,这将是非常省事的。from 操作符就提供了这种功能。
我们通过from
方法去生成一个observable,并用subscribe
尝试去打印其中的信息。
结果是这样的:
next(0)
next(1)
next(2)
next(3)
next(4)
next(5)
completed
需要注意的是,subscribe有许多同名的函数,我们这里使用的是里面做红色标记的:
它把数组的每个元素打印出来,并且有最后一个completed信号。
让我们看看Event<Int>
到底是一个什么概念:
/// Represents a sequence event.
///
/// Sequence grammar:
/// ****next\* (error | completed)** **
public enum Event<Element> {
/// Next element is produced.
case next(Element)
/// Sequence terminated with an error.
case error(Swift.Error)
/// Sequence completed successfully.
case completed
}
extension Event: CustomDebugStringConvertible {
/// Description of event.
public var debugDescription: String {
switch self {
case .next(let value):
return "next(\(value))"
case .error(let error):
return "error(\(error))"
case .completed:
return "completed"
}
}
}
Event本质上是一个带参枚举,它可以表示一个Observable(序列)的事件。而这里[0, 1, 2, 3, 4, 5]的每个元素作为一个事件发了出来。
请回想Swift中的Result类型和Optional类型,是不是似曾相识?
大家有空可以看看我之前的这篇文章:Swift:enum你会用吗?
接下来我们来细化一下这个subscribe
中的方法:
observable.subscribe { (event: Event<Int>) in
switch event {
case .next(let some):
print(some)
case .error(let error):
print(error)
case .completed:
print(event.debugDescription)
}
}
打印的结果更为细化:
0
1
2
3
4
5
completed
some其实就是observable(序列)中包含的真正想要传递的值,在本段例子中它表示的是数组中的元素,我们通过对枚举的switch就可以获取其中的值,并进行数据处理了。
让我们试着类比一下这两个方法array.forEach
和observable.subscribe
,其实都是在为其中的元素做数据处理。
而在Rx中,subscribe
函数的意思代表的是订阅(observable序列)的操作,说白了就是可以了解observable(序列)的中每个元素的行为,可以进行操作。
The equivalence of observer pattern (Observable sequence) and normal sequences (Sequence) is the most important thing to understand about Rx.
了解Observable序列和正常序列(Sequence)的等价性是理解Rx最重要的事情。
总结
-
遵守
Sequence
协议的类型可以用于描述同步产生的序列。 -
Observable
可以用于描述元素异步产生的序列,同步产生的序列当然也可以。
single items | multiple item | |
---|---|---|
synchronous | T getData() | Iterable<T> getData() |
asynchronous | Future<T> getData() | Observable<T> getData() |
很难理解?在这里如果曲线理解的话,你可以认为Observable是一个很特殊的数组,里面的每个元素都可以是一个异步回调。
Array可以通过forEach去调用里面的每个元素,而Observable是通过subscribe在其方法中将异步的回调转换为
一个同步回调,然后处理数据与逻辑。
下一节预告
还是没明白?没事,下一节,我会通过另外一种思维模式,让大家通过另外一个角度来理解Observable。
希望对你的理解Observable打开一扇新的窗。
另外注意
和RxSwift中文文档中约定的一致:由于可被观察的序列(Observable) 名字过长,很多时候会增加阅读难度,所以笔者在必要时会将它简写为:序列。
参考文档
RxSwift/Documentation/GettingStarted.md
RxSwift编写wanandroid客户端现已开源
目前RxSwift编写wanandroid客户端已经开源了——项目链接。
我已经适配iOS的黑暗模式,并进行了一轮CodeReview,记得给个star喔!
附上一张效果图片: