RxSwift基础

写在开始

本文的写作目标受众是刚接触RxSwift、以及还在探索RxSwift的读者。接下来会从4个方面做介绍:为什么用、怎么理解,基本概念及其使用、用的时候注意什么。

为什么用

RxSwift是MVVM模式的最佳伴侣之一。

项目开发采用的基础模式是MVVM,其中M(Model)与V(View)之间往往需要数据的双向绑定,即,M(Model)的变动能及时通知到(View),V(View)的变动能及时更新到M(Model)。如此一来,我们可能会想到KVO,但是如果采用KVO,会发现业务逻辑很大一部分就是在C(Controller),这就变成MVC模式了,而非在MVVM模式。

幸好,有了响应式编程框架,如:RxSwift、ReactiveCocoa等,能很好的实现M(Model)与V(View)之间往往需要数据的双向绑定。

至于,为什么使用RxSwift,而不采用ReactiveCocoa,网上应该很多资料介绍,在此就不做过多的阐述,但我认为都是实现Reactive的框架,主要思想、接口应该基本一致,可能会有一些特性差异(比如冷热信号)。当初决定使用RxSwift的原因有两点:

  1. 之前没有使用过RxSwift,想尝试一下。
  2. RxSwift社区很活跃。

接下来就介绍RxSwift的几个基本概念。

怎么理解

我们在理解RxSwift的时候,可以与监听者模式联想在一起。一个信号量(Observable)可以当做被监听者,订阅者(Observer,在RxSwift中,我们可以认为就是一个闭包。实际上是一个Observer对象分装了这个闭包)则是监听者。一个信号量可以被多个订阅者订阅。当信号量维护的值有变化时,订阅者能收到相应的通知。

基本概念及其使用

在我们打算深层次探索一个开源框架的时候,可能最好的方式就是先熟悉它的基本概念、模仿Demo去使用、然后配合调试去阅读源码。本文要做的主要事情就是介绍它的基本概念、以及一些简单使用。后续,再去分析它的源码实现。

ObservableType和ObserverType

  • ObservableType是一个Protocol,所有的被监听者都实现该协议。最重要的是,定义了最基本的订阅方法func subscribe(_ observer: O) -> Disposable where O.E == E,以及public func asObservable() -> Observable的实现。

  • ObserverType是一个Protocol,所有的监听者都实现该协议。定义了最基本的收到通知后的处理方法func on(_ event: Event),以及public func onNext(_ element: E)public func onCompleted()public func onError(_ error: Swift.Error)实现基本的。

Observable和Observer

  • Observable是一个class,是ObservableType的最基本的实现,同时,也是一个泛型,,这样我们就可以把Swift中的所有类型都包装成一个被监听者类型。一般其子类都会维护一个Observer的list。

  • Observer为后缀的类,都是ObserverType的子类,当调用Observablesubscribe方法都会显式或隐式创建一个以Observer为后缀的的类型,添加到Observable的监听者列表里面。

  • Observable的发送的消息有三类:Next、Error、Completed。后两种会结束整个消息流。对应的Observer处理方式也有三种:onNext、onError、onCompled。

Disposable

Disposable是一个Protocol,定义了一个func dispose()方法,调用Observablesubscribe方法返回的类型,其作用就是给调用者机会从ObservableObserver列表中将该Observer移除。

一般使用过程中,我们都是在使用Observable类型时候,在后面加上takeUntil(self.rx.deallocated)或者disposed(by:disposeBag)来达到释放Observerd的目的。

SubjectType

SubjectType是一个Protocol,继承自ObservableType,但它也可以转换成Observer,可以简单的认为它既是被监听者,也是监听者。两个角色可以随意转换。他的具体实现有(但不限于):

  • PublishSubject:订阅者会错过之前发送过的消息。
  • ReplaySubject:订阅者不会错过之前发送过的消息,可以设置不想错过的消息数目。
  • BehaviorSubject:被监听者会保留最后一条消息,新来的订阅者首先会收到之前保留的这条消息。

具体解释可以参考这里

RxSwift独有的特性

RxSwift除了响应式编程的一些通用功能,自己还拥有一些独有的特性,这SingleCompletableMaybe几个特性,都是PrimitiveSequence的一个别名,可以认为是对Observable的一个封装,其实现如下:

public struct PrimitiveSequence {
    let source: Observable

    init(raw: Observable) {
        self.source = raw
    }
}

Single

顾名思义,Single跟不普通的Observable的不同在于,只会发送一个元素或者一个Error。常用的场景是HTTP请求,往往只返回一个Response或者Error。Single的定义如下:

/// Sequence containing exactly 1 element
public enum SingleTrait { }
/// Represents a push style sequence containing 1 element.
public typealias Single = PrimitiveSequence

public enum SingleEvent {
    /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
    case success(Element)
    
    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)
}

由上面的实现,我们可以看到Single只是收发的事件有两种:一个是.success(Element),另一个就是.error(Swift.Error)

Completable

Completable跟不普通的Observable的不同在于,只会发送一个Completed或者一个Error。当我们不需要关心一个数据流的具体元素是什么,只关心完成与否的时候,就可以用Completable。其定义如下:

/// Sequence containing 0 elements
public enum CompletableTrait { }
/// Represents a push style sequence containing 0 elements.
public typealias Completable = PrimitiveSequence

public enum CompletableEvent {
    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)
    
    /// Sequence completed successfully.
    case completed
}

Maybe

MaybeSingleCompletable的结合,会发送一个元素或者一个Completed或者一个Error,三选一。其定义如下:

/// Sequence containing 0 or 1 elements
public enum MaybeTrait { }
/// Represents a push style sequence containing 0 or 1 element.
public typealias Maybe = PrimitiveSequence

public enum MaybeEvent {
    /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
    case success(Element)
    
    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)
    
    /// Sequence completed successfully.
    case completed
}

Driver

可以认为他是专门为数据模型驱动UI而订制的。它主要是为了解决下面3个问题:

  • 当我们将获取数据的信号bind到某个UI元素的时候,如果获取数据信号发送的是一个Error消息,那么UI元素将无法刷新。Driver初始化的时候可以设置一个:当发生Error的时候的默认值。
  • UI刷新必须在主线程。Driver默认在主线程刷新。
  • 能重放消息,比如:一个页面有两个UI需要用到获取数据的信号,而这个信号是对一个网络请求的封装。那么每次我们订阅那个信号的时候,都会发一次网络请求。而用Driver可以重放最近一次的结果,那么,第二次订阅就不会再触发网络请求了。

用的时候注意什么

说起循环引用,可能大家都不陌生,自OC进入ARC时代,就一直是内存泄漏的罪魁祸首。

而,采用了RxSwift,一不小心就会导致内存泄漏。因为我们才使用MVVM模式的时候,往往是ViewController里面引用ViewModel,然后在RxSwift的闭包中使用到Self.xxx这样的调用,这就容易引起循环引用,从而导致内存泄漏,因此在使用RxSwift的时候应该处处留心,应该时刻谨记以下两点:

  1. 必要的时候在闭包的参数前加上[weak self]这样的声明。如果不确定,该不该加,那就统一加上,一般不会出现问题,因为大部分情况下业务逻辑都是帮随着View出现而调用,View的消失而取消。
  2. 在每个信号订阅后,及时加上takeUntil(self.rx.deallocated)或者disposed(by:disposeBag)

最后

RxSwift是一个比较庞大的库,上面只做了些基本的分享,如果要熟悉所有的API,需要不断阅读文档、反复使用、阅读源码。如果研究透了它,我相信不仅能让我们的开发效率提高,还能加深我们自身对Swift这门语言的理解。一起加油吧!

你可能感兴趣的:(RxSwift基础)