RxSwift:2.Observables

3,027 阅读20分钟

现在我们已经了解到了一些基本概念, 就可以开始使用observables了.

在这篇教程中, 我们会编写几个创建和订阅observables的例子, Observable在刚开始使用的时候可能会有一些抽象, 但请放心, 随着我们慢慢的深入, 并且了解RxSwift中可用的Observable对象的许多类型, 这些问题都会慢慢迎刃而解的.

注意: 如转载本文章, 请联系作者, 并给出文章的源地址, 本示例的代码可以在Observables下载

开始

在本章中, 我们将使用一个Xcode项目, 该项目已经写好了CocoaPods所需的东西, 直接打开终端, 去到当前目录然后输入:

pod install

CocoaPods就会自动的把RxSwift和我们的工程关联起来了.

注意: 该教程使用的是RxSwift 4.4.1版本, Xcode 10.3, 默认是Swift 5.0版本.

什么是Observable

ObservableRx的核心, 我们将花一些事件讨论什么事Observable, 以及如何创建它们和使用它们.

我们将会看到**"Observable", "Observable sequence"和"sequence"Rx中交换使用, 但实际上它们其实都是一样的. 我们甚至偶尔会看到一个"stream", 特别是来自RxSwift的开发人员, 他们接触过很多不同的编程环境. "Stream"其实也是指同样的东西, 但是在RxSwift中, 我们都称它为序列, 而不是"stream", 在RxSwift**中...

图片

…或者与序列有关的东西. Observable只是一个序列, 有一些特殊的功能, 其中一个功能——也是最实用的功能——异步(asynchronous). Observable对象在一段时间内产生事件, 这个过程称为发出(emitting). Observable的事件可以包含值, 比如说基础数据类型, 自定类型的实例, 也可以是手势, 比如点击等等.

最简单的表现形式就是使用时序图, 它只是在时间轴上标记而已.

图片

从做到右的箭头表示事件, 编号的圆圈表示序列的元素. 元素1将被释放, 经过一段时间之后, 元素2和元素3又会被释放掉, 如果要问这里大概需要多少事件.

它可以是Observable对象生命周期的任何一个点, 接下来我们就看看Observable对象的声明周期.

Observable的生命周期

在前面的时序图中, 我们可以看到Observable发出的三个元素, 当一个Observable对象发出一个元素时, 它会在onNext中发出这个元素.

下面是另一个时序图, 这次是一个条从头到结束的Observable事件线.

图片

这个Observable发出了三个tap事件, 最后就结束. 这个过程我们称为completed事件, 因为它已经被终止. 例如我们可能在监听一些事件, 然后完成了.

重要的是Observable对象已经被终止了, 不会再次发出任何的东西, 这是正常的结束, 当然, 有时候事情并不是我们想象的那样顺利, 也会有出错的情况.

图片

在这个时序图中发生了一个错误, 图里用红色的X表示, Observable发送了一个error的事件, 这与Observable在正常情况下完成了事件并且终止没有什么不同, 因为当Observable发出了一个error事件, 那么它也会终止, 并且不会再发出任何东西.

下面有一个快速的介绍:

  • 一个Observable对象会发出一个包含了元素的onNext事件;
  • Observable会一直运行, 直到发出终止事件为止, 例如: error事件和completed事件
  • 一旦Observable对象被终止, 它就法不能再发出事件.

RxSwift的源代码为例, 这些事件表示为枚举:

/// 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
}

这里, 我们可以看到.next事件包含某个元素的实例, .error事件包含Swift .Error, .completed是不包含任何数据的停止事件.

现在我们已经了解了什么是Observable, 以及它可以做什么, 接下来我们将创建一些Observable来看看它们的行为.

创建Observables

从当前文章回到我们的项目工程, 并且替换下面的代码:

@IBAction func createObservable(_ sender: Any) {
    print("--- just, of, from ---")
        // 1
        let one = 1
        let two = 2
        let three = 3
        
        // 2
        let observable = Observable<Int>.just(one)
}

下面是我们在上面代码中所做的:

  1. 定义将在下面的示例中所要使用的整数常量.
  2. 使用带有一个整数的just方法来创建一个Int类型的Observable对象.

just的名字和它所做的事情非常的贴切, 因为它就是创建一个只包含单个元素的Observable, 只是Observable的其中一种类型方法, 然而在Rx中, 这种方法被称为操作符(Operators).

接下来我们继续下一个操作符:

let observable2 = Observable.of(one, two, three)

这次我们没有明确的指定类型, 在猜测它有可能是**[Int]类型的Observable**对象.

按住option + 鼠标左键点击一下, 我们可以到它是一个Int类型的Observable对象, 不是一个数组:

图片

这是因为of操作符可以接受可变参数, Swift能够根据它推断出Observable对象的类型.

图片

如果想要创建一个Observable的数组, 我们可以简单的将一个数组传递进去, 添加下面的代码到工程中:

let observable3 = Observable.of([one, two, three])

再次按住option + 鼠标左键点击一下, 我们就可以看到它确实是一个**[Int]Observable对象, just操作符也可以将数组作为它的单个元素, 这看起来可能有些奇怪, 然而在just**操作符中, 数组只是单个元素, 不是它的内容.

我们还可以用另一个操作符from来创建Observable对象, 在工程中添加下面代码:

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

from操作符可以从数组中创建单个的Observable元素, 按住option + 鼠标左键点击一下, 我们会看到它是一个Int类型的Observable, 而不是**[Int]**, 注意一下, from操作符只接受数组.

现在我们还没有进行操作, 所以Xcode中的控制台目前看起来光秃秃的, 除了介绍了上面三个操作符之后, 我们并没有实际操作什么, 接下来, 我们就来订阅一下这些Observable对象, 来点实际的.

订阅Observable

作为一个iOS开发人员, 我们可能熟悉NotificationCenter, 它会向订阅者发送通知广播, 这和RxSwiftObservable对象不同. 下面是一个UIKeyboardDidChangeFrame通知的观察者的例子, 后面有一个处理相关操作的Block:

let observer = NotificationCenter.default.addObserver(
  forName: UIResponder.keyboardDidChangeFrameNotification,
  object: nil,
  queue: nil) { notification in
  // Handle receiving notification
}

订阅一个RxSwiftObservable对象非常的简单, 我们用观察者去订阅它就可以了, 就相当于把上面的addObserver()替换为subscribe(), 与NotificationCenter不同, Rx中的每个Observable对象都是不一样的, 开发人员通常只会用到它的.default单例.

更重要的是, 一个Observable对象在没有订阅者的情况下是不会直接就发送事件或者执行任何操作.

记住, Observable对象实际上是一个序列的定义, 订阅一个Observable对象实际上更像在Swift标准库的迭代器调用next().

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

不过, 我们订阅Observable要比这个更加的精简, 我们还可以为Observable发出每种事件类型添加处理操作.

回想一下, 一个Observable会发出的.next, .error.completed事件. .next事件将发出的元素传递给应用程序继续处理, .error事件则是一个包含错误信息的实例.

来点实际的代码, 将下面的代码添加到我们示例当中:

@IBAction func subscribe(_ sender: Any) {        
    print("\n--- subscribe ---")

    let one = 1
    let two = 2
    let three = 3

    let observable = Observable.of(one, two, three)
}

这和前面的示例类似, 只是这次我们使用的是of操作符, 现在在这个例子的底部订阅Observable, 并且在闭包里添加一段操作代码:

observable.subscribe { event in
	print(event)
}

按住option + 鼠标左键点击一下subscribe操作符, 我们会看到它接受一个转义的block, 该闭包接受Int类型的事件, 并且不返回任何内容, subscribe会返回一个可以丢弃的闭包, 以管理资源, 稍后我们将会涉及到Disposable.

图片

触发事件后, 我们会看到输出的结果:

--- subscribe ---
next(1)
next(2)
next(3)
completed

Observable对象为每个元素发出.next事件, 然后再发出.completed事件表示终止, 当我们使用Observable时, 通常会对.next事件发出的元素比事件本身更感兴趣.

那么我们如何去访问呢? 我们用下面的代码将之前的订阅代码给替换掉:

observable.subscribe { event in
    if let element = event.element {
        print(element)
    }
}

事件是具有元素属性的, 并且是一个option, 因为.next事件有一个元素, 只要元素不为nil, 则可以使用option绑定来展开元素, 现在我们再次触发, 就会看到控制台上只打印元素, 并不会打印包含元素的事件, 也不会输出.completed事件 .

1
2
3

由于这种模式使用的非常频繁, 所以RxSwift为了让我们更加的简单使用, 还提供了一种操作符, 可以包含Observable对象发出每一种类型的事件: next, errorcompleted.

用下面的代码来代替之前的订阅代码:

observable.subscribe(onNext: { element in
    print(element)
})

现在, 我们只需要处理.next事件的元素, 其他的内容则会被忽略掉. onNext闭包接收.next事件的元素作为参数, 所以我们不用再像之前那样子手动的去检索元素.

现在我们已经了解了如何创建一个或者多个元素的Observable对象, 那么零元素的Observable呢? RxSwift也考虑到了这种情况, 因为提供了一个.empty操作符, 它只会发出.completed事件.

添加下面的例子到我们的工程中:

@IBAction func empty(_ sender: Any) {
    print("\n--- empty ---")
    let observable = Observable<Void>.empty()
}

如果我们没有办法去推断类型, 那么则必须得显式的声明Observable的特定类型, 而empty就是没有推断的内容, 所以必须显式的声明定义类型.

在这种情况下我们使用Void比其他类型都要好, 将下面的代码添加到工程中:

observable.subscribe(
    // 1
    onNext: { element in
        print(element)
},
    // 2
    onCompleted: {
        print("Completed")
})

依次来解释一下:

  1. 处理.next事件, 就像我们在前面的示例中那样.
  2. .completed事件不包含任何的元素, 这里只打印一条消息

在控制台中, 我们会看到empty只发出.completed事件:

--- empty ---
Completed

关于这个.empty有人可能会有疑问, 这个操作符能做什么? 仔细的想一下, 如果我们想返回一个立即终止或者有意为零的Observable元素时, 那么它就非常的有用了.

与这个empty操作符相反的就是never操作符, 是用来创建一个永远不会发出任何东西, 也永远不会终止的Observable对象, 它可以用来表示无限的持续时间, 把下面的例子添加到工程:

@IBAction func never(_ sender: Any) {
    print("\n--- never ---")
    let observable = Observable<Any>.never()

    observable.subscribe(
        onNext: { element in
            print(element)
    },
        onCompleted: {
            print("Completed")
    })
}

一旦我们出发这个事件, 我们只会看到标题头, 然后.next事件和.completed事件是不会输出任何信息的.

到目前为止, 我们使用的都是显式元素或者有值的Observable, 除此之外, 也可以生成一个范围的Observable.

把下面的例子添加到工程:

@IBAction func range(_ sender: Any) {
    print("\n--- range ---")
    // 1
    let observable = Observable<Int>.range(start: 1, count: 10)

    observable
        .subscribe(
            onNext: { i in
                // 2
                let n = Double(i)

                let fibonacci = Int(((pow(1.61803, n) - pow(0.61803, n)) / 2.23606).rounded())
                print(fibonacci)
        })
}

继续来拆解:

  1. 使用range操作符来创建一个从1开始, 数量为10Int类型Observable对象
  2. 计算并输出第n个斐波那契数列

实际上, 有一个比.onNext更好的处理转换元素的操作符, 这个我们会在未来的教程中会学习到.

到目前为止, 除了never()示例之外, 我们一直都在处理Observable对象, 它们会自动的发出.completed事件并终止Observable序列. 这会使得我们将重点放在创建和订阅Observable的机制上, 虽然这样子很方便, 但会掩盖了我们进一步了解Observable, 接下来, 我们细说一下Observable的处理和终止.

处理和终止

有一件事情我们需要记住, 在Observable对象未接收到订阅之前, 是不会做任何事情的, 订阅是用来触发Observable对象的工作, 然后才会使Observable发出事件, 直到它发出.error.completed事件并终止为止, 除此之外, 我们也可以通过取消Observable对象的订阅, 然后终止Observable对象.

把下面的代码添加到工程中:

@IBAction func dispose(_ sender: Any) {
    print("\n--- dispose ---")
    // 1
    let observable = Observable.of("A", "B", "C")
    // 2
    let subscription = observable.subscribe { event in
        // 3
        print(event)
    }
}

简单的介绍:

  1. 创建一个字符串的Observable对象.
  2. 订阅Observable对象, 这次将返回的Observable对象, 然后用一个let变量保存着.
  3. Observableblock回调中处理任务.

如果我们要显式的取消订阅, 我们会调用dispose(). 再次说一下, 取消订阅或处理完订阅之后, 当前示例中的Observable将会停止发出事件.

将下面的代码添加到例子中:

subscription.dispose()

但是这种单独管理每个订阅是非常的繁琐的, 所以RxSwift提供了一个统一管理的DisposeBag类型, 它可以使用添.dispose(by: )方法将subscribe添加到disposeBag中, 每当即将要释放Observable对象时, 都会自动的去调用dispose()方法.

下面的代码添加到工程中:

@IBAction func disposeBag(_ sender: Any) {
    print("\n--- DisposeBag ---")
    // 1
    let disposeBag = DisposeBag()
    // 2
    Observable.of("A", "B", "C")
        .subscribe {
            // 3
            print($0)
        }
        // 4
        .disposed(by: disposeBag)
}

解释一下代码的工作流程:

  1. 创建一个disposeBag.
  2. 创建一个Observable对象
  3. 订阅Observable对象, 并使用Swift标准库的默认参数$0输出内容.
  4. subscribe的返回值添加到disposeBag中.

这将会是我们以后最常用的模式, 创建并订阅一个Observable, 然后立即将subscribe添加到disposeBag中.

为什么要那么麻烦使用disposeBag?

如果我们忘了向disposeBag添加订阅, 或者在订阅完成之后忘了手动添加dispose, 那么就会造成本该结束的Observable对象没有结束, 导致内存泄漏.

幸好的是, Swift编译器会提醒我们没有使用disposables.

在前面的示例里, 我们都是创建Observable对象, 然后再使用.next来输出元素, 现在我们来点不一样的, 使用create操作符, 这个操作符允许我们将指定的Observable对象向订阅者发出所有事件的另一种方式.

把下面的示例添加到代码中:

@IBAction func create(_ sender: Any) {
    print("\n--- create ---")
    let disposeBag = DisposeBag()

    Observable<String>.create { observer in
    }
}

create操作符接受一个名为subscribe的参数, 它工作是提供对Observable调用subscribe的实现, 换一句话说它定义了将发送给订阅者的所有事件, option + 鼠标左键点击一下:

图片

subscribe参数是一个转义闭包, 它接受AnyObserver并返回一个逃逸闭包. AnyObserver是一种泛型的类型, 它可以非常方便的将值添加到一个Observable序列中, 然后将该序列发送给订阅者.

create的实现更改为下面的代码:

Observable<String>.create { observer in
  // 1
  observer.onNext("1")
  // 2
  observer.onCompleted()
	// 3
  observer.onNext("?")
	// 4
  return Disposables.create()
}

代码详情:

  1. 添加一个.next事件到Observable, .onNext(_:)on(.next(_:))的快捷方法.
  2. .completed事件添加到Observable中, 和上面一样, .onCompletedon(.completed)的快捷方法.
  3. 再添加另一个.next事件到Observable.
  4. 返回一个disposable.

注意: 在最后一步, 我们返回的是disposable, 这看起来感觉会很奇怪, 请记住, subscribe操作符返回一个表示订阅的Disposable.create()则是一个空的disposable, 则不会有其他的影响, 但有些disposables就另外说了.

这里提一个问题, 你认为第二个.onNext("?")元素会发给订阅者吗? 为什么呢?

我们来试试, 看看你我的猜测是否是正确的, 添加下面的代码到create实现之后:

.subscribe(
    onNext: { print($0) },
    onError: { print($0) },
    onCompleted: { print("Completed") },
    onDisposed: { print("Disposed")}
)
.disposed(by: disposeBag)

现在我们已经订阅了Observable, 并实现了所有的处理细节, onNext和onError使用了默认参数**$0输出元素和错误信息, 但是我们发现结果则是.next的第一个事件, 接下来就是"Completed""Dispose"**.

第二个.next事件不会打印, 回想一下这其中的原因我们也知道, 因为Observable发出了一个.onCompleted事件然后就终止序列了, 所以后续的.onNext事件则不会再发出.

--- create ---
1
Completed
Disposed

如果我们向Observable添加错误会发生什么样的事情呢? 在示例的顶部添加下面的代码:

enum MyError: Error {
    case anError
}

接下来我们在create中将observer.onCompleted替换成observer.onError:

observer.onError(MyError.anError)

Observable则会发出错误信息, 然后终止序列:

--- create with error ---
1
anError
Disposed

如果我们既没有发出.completed, .error事件, 也没有将subscribe添加到disposeBag中, 那么会发生什么情况呢?

下面是完整的实现:

@IBAction func createWithMemoryLeak(_ sender: Any) {
    enum MyError: Error {
        case anError
    }
    print("\n--- create with memory leak ---")
    let disposeBag = DisposeBag()

    Observable<String>.create { observer in
        observer.onNext("1")
        observer.onNext("?")
        return Disposables.create()
        }
        .subscribe(
            onNext: { print($0) },
            onError: { print($0) },
            onCompleted: { print("Completed") },
            onDisposed: { print("Disposed")}
    )
}

恭喜你, 你刚刚创建了一个无限的Observable序列, 该Observable永远都不会结束.

--- create with memory leak ---
1
?

如果你没法忍受这个示例处于内容泄漏状态, 可以把刚刚我们删掉的.completed, .error事件添加回去, 并且将subscribe添加到disposeBag中.

创建Observable工厂

与其创建一个等待订阅者的Observable对象, 不如创建一个Observable工厂, 为每个订阅者提供一个新的Observable对象.

把这个新例子添加到工程中:

@IBAction func deferred(_ sender: Any) {
    let disposeBag = DisposeBag()
    print("\n--- deferred ---")

    // 1
    var flip = false
    // 2
    let factory: Observable<Int> = Observable.deferred {
        // 3
        flip.toggle()
        // 4
        if flip {
            return Observable.of(1, 2, 3)
        } else {
            return Observable.of(4, 5, 6)
        }
    }
}

解释一下代码:

  1. 创建了一个Bool变量来标记需要翻转返回的Observable对象.
  2. 使用deferred操作符创建一个Int类型Observable对象工厂.
  3. 在每次订阅Observable工厂是, 将翻转一次flip的值
  4. 根据fliptrue还是false返回不同的Observablevalue.

从外部看, 一个Observable对象工厂和普通的Observable没啥区别, 添加下面的代码到示例中:

for _ in 0...3 {
    factory.subscribe(onNext: {
        print($0, terminator: "")
    })
        .disposed(by: disposeBag)
    print()
}

每订阅一次factory就会得到相反的Observablevalue, 先得到123, 然后再得到456, 每有一个新的订阅都会重复这个模式:

--- deferred ---
123
456
123
456

使用特性

Observable的特性, 要比常规的Observable行为范围更小, 它们的使用是可选的, 我们可以在任何一个使用Observable特性的地方使用一个常规的Observable对象, 它们的目的是提供一种方式来更清楚的向代码阅读者或者是API的使用者传达我们的意图, 使用Observable的特性, 可以使得我们的代码更加的直观.

RxSwift有三种特性: Single, MaybeCompletable, 在不了解它们的情况下, 你能猜到它们是做什么的吗?

Singles只会发出.success(value).error事件, .success(value)实际上是.next.completed事件的组合, 这对于使用一次性进程非常有用, 一次性进程要么成功输出一个value, 要么就失败, 例如下载数据或从硬盘加载数据. Completable只会发出.completed.error事件, 它不会发出任何的值, 只关于某个操作成功完成或者是失败了, 例如文件的写入, 我们就可以使用completable.

最后, MaybeSingleCompletable的组合, 它可以发出.success(value), .completed.error事件, 如果我们需要实现一个可能会成功或者失败的操作, 并且在成功的时候返回一个值, 那么Maybe就是我们所需要的...

我们会在未来的教程中学习更多有关于RxSwift的特性, 现在我们来运行一个基本的示例, 在工程中, 我们有一个hello.text文件, 我们将使用Observable的特性来加载并输出这个文本内容.

图片

把下面的例子添加到我们的工程中:

// 1
enum FileReadError: Error {
    case fileNotFound, unreadable, encodingFailed
}
// 2
private func loadText(from name: String) -> Single<String> {
    // 3
    return Single.create { single in
    }
}

解释一下我们要在代码中做的事情:

  1. 创建一个错误类型的枚举, 用来对从磁盘中读取文件可能会发生失败的一些情况
  2. 创建一个函数, 该函数返回一个从磁盘中加载的文本内容.
  3. 创建并返回Single

create闭包中添加下面的代码来实现我们需要的操作:

// 1.
let disposable = Disposables.create ()
// 2
guard let path = Bundle.main.path(forResource: name, ofType: "txt") else {
    single(.error(FileReadError.fileNotFound))
    return disposable
}
// 3
guard let data = FileManager.default.contents(atPath: path) else {
    single(.error(FileReadError.unreadable))
    return disposable
}
// 4
guard let contents = String(data: data, encoding: .utf8) else {
    single(.error(FileReadError.encodingFailed))
    return disposable
}
// 5
single(.success(contents))
return disposable

我们解释一下这段代码:

  1. create方法的subscribe闭包必须返回一个disposable, 因为我们需要在不同的地方返回它, 所以另外抽出来声明
  2. 获取文件名的路径, 如果获取失败, 则返回.fileNotFounddisposable
  3. 获取该路径中的数据, 如果获取失败则返回.unreadabledisposable
  4. 将数据转换为字符串, 如果编码失败则返回..encodingFaileddisposable
  5. 如果都通过了上面四步, 那就成功了, 并且将内容添加到single中, 然后返回disposable.

现在我们可以来使用这个函数了, 将下面的代码添加到工程中:

// 1
loadText(from: "hello")
// 2
.subscribe {
  // 3
    switch $0 {
    case .success(let string):
        print(string)
    case .error(let error):
        print(error)
    }
}
    .disposed(by: disposeBag)

在这里我们做的操作是:

  1. 调用loadText(from:), 然后传递你要读取的文件名.
  2. 订阅函数返回的single.
  3. 这里我们使用switch来进行下一步操作, 成功则输出文本内容, 失败则打印错误信息.

现在我们应该可以看到控制台中输出的文本内容:

--- single ---
Hello RxSwift

如果我们将文件名换成其他的话, 应该会打印出未找到文件的错误信息.

剩下CompletableMaybe这里就不做介绍了, 工程中有对应的代码:

挑战

熟能生巧, 我们将实践在本章中所学到的只是来完成这些挑战, 并且获得更多关于使用Observable对象的知识.

挑战1: 产生附加效果

在前面的never操作符实例中, 没有输出任何的内容, 那是因为我们输出的内容是添加到subscribe之中, 如果我们能添加到在这之前, 并且再将subscribe添加到disposeBag, 那我们就可以看到消息的输出了.

还有一个非常实用的操作符, 它允许我们在不印象Observable对象的情况额外添加一些我们想做的事情.

do操作符将允许我们添加附加效果, 也就是说, 不管这个Observable对象会发出什么样的事件, do只是将事件传递链接到下一个操作符中, do这个操作符还包含一个onSubscribe的闭包, 我们将会在这里处理额外的事情.

使用do操作符的方法是do(onNext:onError:onCompleted:onSubscribe:onDispose), 你可以在这里实现任何你想做的事情.

我们将使用do操作符改造一下我们的never示例, 在改造的时候, 千万别忘了把subscribe添加到disposeBag中.

挑战2: 打印调试信息

除了刚刚我们提过的do操作符可以作为Rx的调试方式之外, 还有一种操作符叫做debug操作符, 它将为一个Observable对象打印出每个事件信息.

它有几个可选参数, 可能最有用的就是包含一个标识符字符串, 该字符串会打印出来, 在复杂的Rx链中, 我们可以在多个位置添加debug操作符, 这可以帮助我们区分打印出来的源subscribe.

通过使用debug操作符替换do操作符, 并为其提供一个字符串作为标识符.

总结

生命周期:

1.当Observable事件完成时会发出Completed事件, 代表事件结束;

2.当Observable在未完成事件前发生了错误, 该事件也会结束, 并且抛出error事件;

3.当Observable的事件完成了之后就不会再发出任何事件了.

注意点:

  • Observable不会发送任何事件, 也不会执行任何工作, 直到它拥有了一个订阅者为止.
  • 使用subscribe()函数订阅Observable
  • 如果订阅的事件具有元素性, 则可以通过使用element展开元素, 并且是会打印元素, 不会打印completed事件.
  • 如果使用.create()操作符创建的Observable, 在处理完事件之后, 一定要调用一下.onCompleted()或者是.onError(), 并且在subscribe时一定要调用disposed(by: DisposeBag), 否则Observable永远不会被释放, 造成内存泄漏.

RxSwift的三种特性

  1. Single:
    • 将发出.success(value).error事件, 而.success(value)实际上是.next.completed事件的组合
    • 常用在下载数据, 或者从磁盘读取数据这种一次性的操作.
  • 不会共享附加效果
  1. Completable:
    • 只会发出.completed.error事件, 不会发出任何值
    • 可用在文件写入或者是某个操作
  • 不会共享附加效果
  1. Maybe:
    • SingleCompleable的组合, 它会发出.success(value), .completed或者.error事件
    • 常用在在进行某个操作时, 并且在成功时可以返回一个值
    • 不会共享附加效果