阅读 512

RxSwift学习——理解Observable(一)| 8月更文挑战

前言

就我学习RxSwift的感觉,各种文档和说明都会说Observable是Rx中最最最核心的部分。

然而,正是因为它核心、关键,理解起来也不容易。编程本来就是非常抽象的事情,又想把抽象中的知识点梳理清楚亦是困难。

最近上了公司的一节培训课,说真正的大佬,对于非常深奥的问题和概念,总能一语中的,通俗易懂的说明白。

针对Observable我也一直在思考,如何给大家解释清楚,吃饭和睡觉都在想这事。

下面就给大家带来我的理解。

先解释一下Observable这个单词

image.png

大家注意它是一个形容词,意思是可观察得到的

官方中文文档的解释是:可被观察的序列(Observable)

由于名字过长,很多时候会增加阅读难度,所以必要时会将它简写为:序列

序列,这个词是不是特别熟悉?英文是sequence,是不是想起了什么?没错,Swift中有一个Sequence协议。

image.png

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()
复制代码

image.png

当你在使用 Observable 时,如果能够直接将其他类型转换为 Observable,这将是非常省事的。from 操作符就提供了这种功能。

我们通过from方法去生成一个observable,并用subscribe尝试去打印其中的信息。

结果是这样的:

next(0)
next(1)
next(2)
next(3)
next(4)
next(5)
completed
复制代码

需要注意的是,subscribe有许多同名的函数,我们这里使用的是里面做红色标记的:

Snip20210803_5.png

它把数组的每个元素打印出来,并且有最后一个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.forEachobservable.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 itemsmultiple item
synchronousT getData()Iterable<T> getData()
asynchronousFuture<T> getData()Observable<T> getData()

很难理解?在这里如果曲线理解的话,你可以认为Observable是一个很特殊的数组,里面的每个元素都可以是一个异步回调。

Array可以通过forEach去调用里面的每个元素,而Observable是通过subscribe在其方法中将异步的回调转换为一个同步回调,然后处理数据与逻辑。

下一节预告

还是没明白?没事,下一节,我会通过另外一种思维模式,让大家通过另外一个角度来理解Observable。

希望对你的理解Observable打开一扇新的窗。

另外注意

和RxSwift中文文档中约定的一致:由于可被观察的序列(Observable) 名字过长,很多时候会增加阅读难度,所以笔者在必要时会将它简写为:序列

参考文档

Observable - 可监听序列

RxSwift/Documentation/GettingStarted.md

ReactiveX/Introduction

RxSwift编写wanandroid客户端现已开源

目前RxSwift编写wanandroid客户端已经开源了——项目链接

我已经适配iOS的黑暗模式,并进行了一轮CodeReview,记得给个star喔!

附上一张效果图片:

RPReplay_Final1625472730.2021-07-05 16_13_58.gif

文章分类
iOS
文章标签