美文网首页RxSwift
RxSwift #02 | Observables

RxSwift #02 | Observables

作者: JeremyTechBlog | 来源:发表于2021-11-29 12:18 被阅读0次

    Everything is a sequence

    Observable 是 RxSwift 的核心。

    在学习 RxSwift 的过程中,我们经常能够看到 observable, observable sequence, sequence, stream 之类的名词。

    需要注意的,在 Rx 的世界中,这些其实都是指的同一个东西,也就是序列,也称为订阅流。

    Everything is a sequence.

    一个 observable 就是一个 sequence, 事实上,它是异步的,observable 在一段时间内产生事件(event),这被称为发出(emitting)。就比如点击事件,每点击一次按钮,就发出一个点击事件(emitting a tap event)。

    订阅流通常用下面这种 marble diagrams 表示,中文直译是“大理石图”:

    • 从左到右的箭头表示时间轴
    • 带有编号的圆圈表示元素,代表着每一个事件(event),也就是 元素 = 事件。

    Lifecycle of an observable

    上图中,这个 observable 发出 3 个点击事件,然后结束。最右边的竖线,代表 completed 事件,也意味着整个订阅流的终止(terminated)。

    比如:点击一个按钮,发出了 3 个点击事件,然后按钮所在的 view 被 dismiss 掉,发出一个 completed 事件,然后整个订阅流就终止了,被终止的订阅流不能再发出任何事件。

    上图中的❌代表着一个 error 事件,和 completed 事件类似,当一个 observable 发出一个 error 事件,这个订阅流就被终止了,不能再发出任何事件。

    总结如下:

    • 一个 observable 发出 next 事件,next 事件可以携带自定义 element。
    • 当终止(terminated)事件发出的时候,也就是 completed 或者 error 事件发出的时候,订阅流不能再发出事件。
    /// 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
    }
    
    

    Event 本质上是一个 enum, 通过 Swift enum 的能够关联值的特性,实现了 next 事件可以关联 element,以及 error 事件可以关联一个 Swift.Error

    Creating observable

    RxSwift 中内置了多种创建 observable 的方式:

    just

    example(of: "just, of, from") {
      // 1
      let one = 1
      let two = 2
      let three = 3
    
      // 2
      let observable = Observable<Int>.just(one)
    }
    
    

    of

    let observable2 = Observable<Int>.of(one, two, three)
    let observable3 = Observable<Int>.of([one, two, three])
    
    

    from

    let observable4 = Observable<Int>.from([one, two, three])
    
    

    你可以在你的 playground 中输入上述代码,编译后你会发现,控制台上没有输出任何东西。

    因为你还没有通过订阅去做任何事情。

    Subscribing to observable

    在上一章 RxSwift #01 | 函数式编程和观察者模式 中,我们学习了观察者模式是如何实现的。在 RxSwift 中,subscribe() 其实就是把 observer 添加到 observable 的观察者列表中。

    更重要的是,在有 subscriber 之前,observable 是不会发出任何事件的。记住,一个 observable 实际上是一个 sequence 的定义。订阅一个 observable 更像是在 Swift 标准库中调用 Iterator 的 next()

    let sequence = 0..<3
    
    var iterator = sequence.makeIterator()
    
    while let n = iterator.next() {
      print(n)
    }
    
    /* Prints:
     0
     1
     2
     */
    
    

    之前我们学习了如何定义一个 observable, 下面让我们看看如何订阅一个 observable:

    example(of: "subscribe") {
      let one = 1
      let two = 2
      let three = 3
    
      let observable = Observable.of(one, two, three)
    
        observable.subscribe { event in
          print(event)
        }
    }
    /**
        next(1)
        next(2)
        next(3)
        completed
    **/
    
    

    Disposing and Terminating

    记住,一个 observable 直到被订阅之前,不会做任何事。也可以理解为,是订阅触发了 observable 工作,使它发出新的事件,直到 error 或者 completed 事件终止了订阅流。

    然而,你可以通过手动取消订阅来终止一个 observable。

    example(of: "dispose") {
      // 1
      let observable = Observable.of("A", "B", "C")
      // 2
      let subscription = observable.subscribe { event in
        // 3
        print(event)
      }
        // 4
        subscription.dispose()
    }
    
    

    上述示例代码中,做了以下这些事情:

    1. 定义一个 observable
    2. 订阅一个 observable, 并将返回值 Disposable 类型的对象用一个叫做 subscription 的变量持有
    3. 打印每一个发出的事件
    4. 通过调用 dispose(), 手动取消订阅,此时 observable 不会再发出任何事件。

    DisposeBag

    每次手动去 dispose 一个订阅是很繁琐的,而且很容易忘记,这样就会导致内存泄漏。

    RxSwift 提供了 DisposeBag, 一个 disposeBag 持有了多个 disposable 对象,每个 disposable 对象通过调用 disposed(by:) 方法,将自己添加到 disposeBag 中。在 disposeBag 即将销毁的时候,会一次调用自己持有的每一个 disposable 对象的 dispose() 方法。

    let observable = Observable<String>.create { observer in
      // 1
      observer.onNext("1")
    
      // 2
      observer.onCompleted()
    
      // 3
      observer.onNext("?")
    
      // 4
      return Disposables.create()
    }
    // 这里的最后一步,返回一个 Disposables, 第一次看可能会觉得奇怪
    // 记住,subscribe 操作一定要返回一个 Disposables,代表着一个订阅
    
    observable
        .subscribe(
          onNext: { print($0) },
          onError: { print($0) },
          onCompleted: { print("Completed") },
          onDisposed: { print("Disposed") }
        )
        .disposed(by: disposeBag)
    
    /**
    output:
    1
    completed
    disposed
    **/
    
    

    如果你忘记了把一个订阅(subscription, also a disposables)添加到 disposeBag, 或者忘记手动调用 dispose 方法,或者没有事件去终止 observable,那么你将可能会导致一个内存泄漏。

    Using Traits

    在 RxSwift 中,有三种 traits:

    • Single
    • Completable
    • Maybe

    正如他们的含义一样——特性,它们拥有不同的特性:

    Single

    只会发出一个 success(value) 或者一个 error(error) 事件,success(value) 实际上是 next(value) 和一个 completed 事件的组合。

    这对一次性过程很有用,这些过程要么成功并产生一个值,要么失败,例如在下载数据或从磁盘加载数据时。

    asSingle() 确保你最多只能得到一个元素,如果源序列发出的元素超过一个,则抛出错误。

    Completable

    只会发出一个 completed 或者一个 error(error) 事件,不会发出任何 next(value) 事件。

    当你只关心事件是否成功完成的时候十分有用,比如写入文件。

    Maybe

    最后,Maybe 是一个 Single 和 Completable 的组合体。它可以发出一个 success(value)completederror(error)

    如果你需要实现一个既可以成功也可以失败的操作,并且可以选择在成功时返回一个值,那么你就可以选择使用 Maybe。

    相关文章

      网友评论

        本文标题:RxSwift #02 | Observables

        本文链接:https://www.haomeiwen.com/subject/tdtlxrtx.html