RxSwift学习——理解Observable(二)

896 阅读6分钟

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

前言

上一节,我们通过类比Array与Observable,来讲解Observable(序列)的特性。

本节我会通过现实中的例子来具现化Observable,这种看得见摸得着的事物,希望可以加强对序列的理解。

现实中的流水线

不知道大家发现本次我的文章首页配图,和我以往的风格非常不同,以往我的配图风格,那么是和编程有关的技术图片,要么来一张ACG图片。

而这次我的配置是一个生产流水线场面,注意是流水线。而本次我们类比的就是Observable与流水线。

我们先来看看流水线是干嘛的:

流水线,又称装配线,工业上的一种生产方式,指每一个生产单位只专注处理某一个片段的工作,以提高工作效率及产量。

更多理解请阅读这里

对于流水线的理解非常重要,对于后面Rx的理解都可以起到很重要的作用。

物品的单一性

单纯的流水线,它主要用于传输物品,比如我们这次配图的流水线,它就是用来运输可乐,一般情况,一条生产流水线都是生产同种物品,因为这样不用区分物品类型。

我们来看看Observable的定义:

public class Observable<Element> : ObservableType {
    .
    .
    .
    代码省略
}

Observable是带有泛型约束,也就是说Observable中的元素都是同一种类型,这和流水线上传输单一的物品类型相似。

这里如果我们要对可乐的流水线定义成Observable,我们可以这么表示:

class CocaCola {}

let observable = Observable.just(CocaCola())

Observable中的just与frome区别

上面我们使用的Observable中,更精确应该是协议ObservableType中的just来构建一个拥有单一元素的序列。

让我们来看看just

创建 Observable 发出唯一的一个元素

just 操作符将某一个元素转换为 Observable

extension ObservableType {

    /// Returns an observable sequence that contains a single element.
    public static func just(_ element: Self.Element) -> RxSwift.Observable<Self.Element>

    /// Returns an observable sequence that contains a single element.
    public static func just(_ element: Self.Element, scheduler: RxSwift.ImmediateSchedulerType) -> RxSwift.Observable<Self.Element>

}

它和上节使用的from,恰恰相反,frome是将类数组的数据转为序列:

extension ObservableType {
    /// Converts an array to an observable sequence.
    public static func from(_ array: [Self.Element], scheduler: RxSwift.ImmediateSchedulerType = CurrentThreadScheduler.instance) -> RxSwift.Observable<Self.Element>
    
    /// Converts a sequence to an observable sequence.
    public static func from<Sequence>(_ sequence: Sequence, scheduler: RxSwift.ImmediateSchedulerType = CurrentThreadScheduler.instance) -> RxSwift.Observable<Self.Element> where Sequence : Sequence, Self.Element == Sequence.Element

}

1dc0acdd3057b5673cedc0366e15c79f.jpeg

观察事件

大家可以想象一下,如果想象不出来,可以去找找生产流水线的视频。

流水线一刻也不间断的运行着,人通过眼睛一刻不停的观察流水线的运行:

  • 当有物品被放上来的时候,它就一个接一个一个运输

    • 你永远无法知道,流水线上什么时候有物品在运输,什么时候又没有,它是一个Future,是一个异步

    • 流水线上运输是一个异步的物品

  • 当流水线的运行发生错误的时候,一般的工控设计会通过蜂鸣器报警

    • 一般流水线报警,基本就停止工作了。
  • 当流水线的长期没有物品运输的时候,工控设计会通过检查,认为流水线上没有货物,流水线减速或者停止

    • 关于这点,大家参照扶手电梯的情况就能看出,当没有人的时候,扶手电梯不运行或者运行的很慢,有人站上去的时候,又恢复正常运行。

    • 其实扶手电梯也可以看成是一个流水线。


流水线说完了,我们再来看看Observable。还是之前的代码:

通过from函数生成序列,并且通过subscribe观察序列的中元素。

let array = [0, 1, 2, 3, 4, 5] 

let observable = Observable.from(array) 

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)

    }

}.disposed(by: rx.disposeBag)

event是一个枚举:

  • next看到一个又一个元素被发出。

  • 当有error出现的时候,抛出error,并且在error之后的元素不会再被发出。

  • 当序列中的元素被全部发出后,complete。

对比流水线与Observable,你就会发现事情总是惊人的相似。Event枚举基本上概括了流水线上的一些典型特征发生的事件。

为什么说是典型特征事件,是因为流水线会出现的状况非常之多,但是代码概括和归纳了大的事件类型。

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
}

我甚至觉得Rx的诞生与演化并不是偶然,而是人类在生产劳动中的通过代码总结的一种产物,因为比起编程,流水线的生产方式,已经存在的太久了。

1769年,英国人乔赛亚·韦奇伍德开办埃特鲁利亚陶瓷工厂,在场内实行精细的劳动分工,他把原来由一个人从头到尾完成的制陶流程分成几十道专门工序,分别由专人完成。这样一来,原来意义上的“制陶工”就不复存在了,存在的只是挖泥工、运泥工、扮土工、制坯工等等制陶工匠变成了制陶工场的工人,他们必须按固定的工作节奏劳动,服从统一的劳动管理。

(根据上述资料可以明确看出韦奇伍德的这种工作方法已经完全可以定义成为“流水线”。另一说是亨利·福特发明了流水线装配工艺,这一点显然是不准确的,因为亨利·福特出生于1863年,比韦奇伍德所生活的年代晚了九十多年)

一股车道

如果你觉得,流水线依旧不够熟悉,请回味一下,上面说的扶手电梯,或者是一个一股车道,而你就是站在车道边数车的人:

image.png

  • 你不可能知道车什么时候来,它也许在不久的将来从你身边呼啸而过,也许等了很久,也不会有车来,所以只能静静的观察,车来了一辆,数一辆。

  • 车是一个异步元素。

  • 一股车道不太好理解Event事件。

总结

  • 上一节我们通过编程语言的中Array与Observable类比,来理解序列。

  • 本节,我们通过现实中的流水线与Observable对比,通过具现化的方式来理解序列。

  • 工控的编程逻辑思维可以用于理解Rx。

  • 在有些编程语言中,会使用Stream来表示序列,也是很有道理的。例如Dart的异步编程框架、Swift中的Combine框架。

下一节预告

不管是工控,还是编程,我们总是面临选型的问题,Observable是最为普遍的序列,另外Rx也为我们提供一些特例化的序列进行选型。

下一节来了解一下它们吧。

参考文档

RxSwift中文文档/just

RxSwift中文文档/from

RxSwift编写wanandroid客户端现已开源

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

我进行了一轮CodeReview,并增加了一些小功能:

  • 添加了iOS的黑暗模式适配

  • 上拉加载更多使用了无感知功能

  • MBProgressHUD替换为SVProgressHUD

记得给个star喔!

附上一张效果图片:

RPReplay_Final1627969241.2021-08-03 13_44_57.gif