走进RXSwift

565 阅读5分钟

为什么要用RXSwift?倒不如说为什么要用ReactiveX,使用它有什么好处

ReactiveX所代表的是响应式函数编程,也就是说可以通过可监听序列和函数式编程,让数据/事件流和异步任务能够更方便的序列化处理。简单来说就是:

  • 复合 - Rx 就是复合的代名词

  • 复用 - 因为它易复合

  • 清晰 - 因为声明都是不可变更的

  • 易用 - 因为它抽象的了异步编程,使我们统一了代码风格

  • 稳定 - 因为 Rx 是完全通过单元测试的

函数式编程

需要我们将函数作为参数传递,或者作为返回值返还。使我们可以通过组合不同的方法,以及不同的函数来获取目标结果。

响应式编程

业内经典的实例就是ReactiveCocoa,它都敢叫Cocoa,足以说明它的强大之处,事实上,它就是KVO的一个灵活展示。不需要考虑调用顺序,只需要知道考虑结果,类似于蝴蝶效应,产生一个事件,会影响很多东西,这些事件像流一样的传播出去,然后影响结果,借用面向对象的一句话,万物皆是流。是把操作尽量写成一系列嵌套的函数或者方法调用。

函数响应式编程

是种编程范式。它是通过构建函数操作数据序列,然后对这些序列做出响应的编程方式。它结合了函数式编程以及响应式编程

数据绑定(订阅)


可监听序列绑定到观察者上,实现同步监听。

关键定义理解

Sequence(序列):把事件操作,可以看做一个序列,每次的改变都是一个序列,如一个TextFiled中的文本改变一个按钮的点击,或者一个网络请求结束等。

Obserable(监听事件或可监听序列):每一次对事件改变的处理。

Observer(观察者响应事件):观察事件(UI、数据)的改变。

nevet(发生事件):subscribe后面发生的哈哈,好理解吧,如构建函数里面的onNext,onError, onCompleted 事件。

Disposable (释放):释放已经不在使用的监听资源,手动dispose,自动DisposeBags。

Schedulers(调度器):实现线程的调度。

序列、事件、观察者

RXSwift把每一个操作事件,看做一个序列

任何可以响应事件的行为都是观察者



如何学习

  • Observable - 可监听序列:产生事件

我们的很多操作都可以用序列来表示,Observer用于描述产生的序列。

let numbers: Observable<Int> = Observable.create { observer -> Disposable in
    observer.onNext(0)
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    observer.onCompleted()
    return Disposables.create()
}

  • Observer - 观察者:响应事件

观察者是用来监听事件,然后他需要对这个事件做出响应,如点击按钮后的弹出提示框

在RX中观察者是在订阅(subscribe)后,由 onNextonErroronCompleted的这些闭包构建出来的。

如何自定义观察者?

本身RX已经提供了去实现观察者的方法,自定义参考AnyObserver和Binder

**AnyObserver
可以用来描述任意一种观察者
用户名提示语是否隐藏
usernameValid
    .bind(to: usernameValidOutlet.rx.isHidden)
    .disposed(by: disposeBag)
    
看作是,自定义观察者
let observer: AnyObserver<Bool> = AnyObserver { [weak self] (event) in
    switch event {
    case .next(let isHidden):
        self?.usernameValidOutlet.isHidden = isHidden
    default:
        break
    }
}

usernameValid
    .bind(to: observer)
    .disposed(by: disposeBag) 

**Binder
主要用于观察UI事件,具备两个特征:
1.不会处理错误事件
2.确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler)
let observer: Binder<Bool> = Binder(usernameValidOutlet) { (view, isHidden) in
	它的响应事件只会处理event
    view.isHidden = isHidden
}

usernameValid
    .bind(to: observer)
    .disposed(by: disposeBag)

重点:观察者复用

//是否隐藏
extension Reactive where Base: UIView {
  public var isHidden: Binder<Bool> {
      return Binder(self.base) { view, hidden in
          view.isHidden = hidden
      }
  }
}

//是否可点击
extension Reactive where Base: UIControl {
  public var isEnabled: Binder<Bool> {
      return Binder(self.base) { control, value in
          control.isEnabled = value
      }
  }
}

//label的当前文本
extension Reactive where Base: UILabel {
  public var text: Binder<String?> {
      return Binder(self.base) { label, text in
          label.text = text
      }
  }
}

  • Observable & Observer

许多UI空间都存在这种特性,他们既是可被监听的序列同时也是观察者。

**AsyncSubject
如果订阅前没有任何元素,只会监听订阅后的最后一个元素
let disposeBag = DisposeBag()
let subject = AsyncSubject<String>()

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")
subject.onNext("🐹")
subject.onCompleted()

输出结果
Subscription: 1 Event: next(🐹)
Subscription: 1 Event: completed

**PublishSubject
只监听订阅后的元素
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🅰️")
subject.onNext("🅱️")

输出结果
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)

**ReplaySubject(获取全部元素,可以添加设置条件,如指定元素和限制时间段内)
// 1.先判断条件
// 2.subscribe前的内容:从后往前订阅 subscribe后的内容:不受影响
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🅰️")
subject.onNext("🅱️")

输出结果
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)

**BehaviorSubject
//1.先判断订阅前是否有新的元素,如果没有就采用初始化时的默认元素
//2.不影响订阅后的元素
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "🔴")

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🅰️")
subject.onNext("🅱️")

subject
  .subscribe { print("Subscription: 3 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🍐")
subject.onNext("🍊")

输出结果
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
Subscription: 3 Event: next(🅱️)
Subscription: 1 Event: next(🍐)
Subscription: 2 Event: next(🍐)
Subscription: 3 Event: next(🍐)
Subscription: 1 Event: next(🍊)
Subscription: 2 Event: next(🍊)
Subscription: 3 Event: next(🍊)

**Variable
变量监听(现在RXSwift5被弃用了)

**ControlProperty
专门用于描述 UI 控件属性的,它具有以下特征:
1.不会产生 error 事件
2.一定在 MainScheduler 订阅/监听(主线程)
3.共享状态变化

  • Operator - 选择操作符:创建变化组合事件

操作符帮助我们构建所需要的序列。

如何选择合适的操作符?

beeth0ven.github.io/RxSwift-Chi…

  • Disposable - 管理绑定(订阅)的生命周期

    DisposeBag 清除包

    takeUntil 自动取消订阅

  • Schedulers - 线程队列调配

用于控制任务在哪个线程或者队列运行

rxData
	1.子线程控制数据
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
    2.主线程监听处理结果,刷新UI
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { [weak self] data in
        self?.data = data
    })
    .disposed(by: disposeBag)

使用 subscribeOn

我们用 subscribeOn来决定数据序列的构建函数在哪个 Scheduler 上运行。以上例子中,由于获取 Data需要花很长的时间,所以用 subscribeOn 切换到 后台 Scheduler 来获取 Data。这样可以避免主线程被阻塞。

使用 observeOn

我们用 observeOn来决定在哪个 Scheduler 监听这个数据序列。以上例子中,通过使用 observeOn方法切换到主线程来监听并且处理结果。

MainScheduler:主线程
SerialDispatchQueueScheduler:抽象了串行,执行串行任务的调度
ConcurrentDispatchQueueScheduler:抽象了并行,执行并行任务的调度
OperationQueueScheduler:抽象了NSOperationQueue,控制最大并发数量


最后

学习RXSwift是一个漫长的过程,但是熟练过后肯定会对这些高阶的编程思想有所理解,以上是个人理解,不足之处还望指出,希望多多支持。