本文主要嘗試闡述
- 什么是 FRP
- RxSwift的幾個(gè)基礎(chǔ)概念
- RxSwift的最簡(jiǎn)單使用流程
- RxSwift是怎么通過(guò)基本流程來(lái)實(shí)現(xiàn)事件響應(yīng)的
FRP
FRP全稱為 Functional Reactive Programming, 即函數(shù)響應(yīng)式編程哪痰。
函數(shù)式編程
強(qiáng)調(diào)每個(gè)程序都能夠被反復(fù)分解為越來(lái)越小的模塊單元,而所有這些塊可以通過(guò)函數(shù)裝配起來(lái)碧信,以定義一個(gè)完整的程序润梯。
響應(yīng)式編程
在響應(yīng)式編程當(dāng)中赠橙,a:=b+c聲明的是一種綁定關(guān)系耽装。(a與b狡耻、c綁定起來(lái)了借浊,所以b减宣、c的變化會(huì)影響a界轩,這也就是所謂【變化傳播】)
RxSwift 的 基礎(chǔ)概念
可觀察序列 Observable
Observable 是RxSwift 框架的核心概念画饥,它是RxSwift的數(shù)據(jù)源
請(qǐng)求接口的網(wǎng)絡(luò)數(shù)據(jù),可以定義成一個(gè)Observable a
請(qǐng)求數(shù)據(jù)庫(kù)的數(shù)據(jù)浊猾,也可以定義成一個(gè)Observable b
而我們的界面顯示的數(shù)據(jù) c 可以綁定到 a + b的數(shù)據(jù)流上抖甘,即 c := a + b
我們可以想象到 c 也是一個(gè) Observable ,
而 + 和 := 操作 在RxSwift中定義了相應(yīng)的函數(shù)式
在RxSwift中只要實(shí)現(xiàn)了 ObservableType協(xié)議的類都可以認(rèn)為是 Observable葫慎,
ObservableType的定義如下
public protocol ObservableType: ObservableConvertibleType {
func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable
where Observer.Element == Element
}
從協(xié)議的定義可以認(rèn)為衔彻,要成為一個(gè)可觀察序列,只要實(shí)現(xiàn)subscribe方法即可偷办,
而subscribe方法有一個(gè)Observer類型的參數(shù)艰额,并且Observer需要實(shí)現(xiàn)ObserverType協(xié)議,下面我們會(huì)介紹觀察者Observer
觀察者 Observer
觀察者椒涯,見(jiàn)名知意我們可以認(rèn)為柄沮,它有一個(gè)被觀察者,即Observable,通過(guò)普通的觀察者模式祖搓,我們應(yīng)該知道狱意,一般觀察者會(huì)定義一些行為來(lái)相應(yīng)Observable的變化。我們來(lái)看看觀察者的定義
public protocol ObserverType {
/// The type of elements in sequence that observer can observe.
associatedtype Element
@available(*, deprecated, message: "Use `Element` instead.")
typealias E = Element
/// Notify observer about sequence event.
///
/// - parameter event: Event that occurred.
func on(_ event: Event<Element>)
}
與Observable類似拯欧,要成為一個(gè)觀察者详囤,只要實(shí)現(xiàn)ObserverType協(xié)議即可。
以上介紹了RxSwift的兩個(gè)基礎(chǔ)概念, Observable和Observer
那么Rxswift是怎么通過(guò)這兩個(gè)對(duì)象來(lái)處理業(yè)務(wù)的呢镐作?
RxSwift的基本使用流程
// 1. 創(chuàng)建序列
let observable = Observable<Int>.create { (observer: AnyObserver<Int>) -> Disposable in
}
// 2. 訂閱序列
let disposable = observable.subscribe(onNext: { (value) in
})
// 3. 資源回收
disposable.disposed(by: disposeBag)
RxSwift 處理事務(wù)的流程如上
- 創(chuàng)建一個(gè)可觀察序列
- 通過(guò)觀察者訂閱可觀察序列
- 將訂閱的資源放入資源回收包中統(tǒng)一回收
舉個(gè)例子纬纪,使用RxSwift來(lái)處理button的點(diǎn)擊事件
button.rx.tap.subscribe(onNext: {
}).disposed(by: disposeBag)
為了驗(yàn)證流程, 我們需要查看button.rx.tap是否創(chuàng)建了一個(gè)Observable滑肉,來(lái)帶 UIControl + Rx.swift文件包各,查看到源碼如下
public func controlEvent(_ controlEvents: UIControl.Event) -> ControlEvent<()> {
let source: Observable<Void> = Observable.create { [weak control = self.base] observer in
MainScheduler.ensureRunningOnMainThread()
guard let control = control else {
observer.on(.completed)
return Disposables.create()
}
let controlTarget = ControlTarget(control: control, controlEvents: controlEvents) { _ in
observer.on(.next(()))
}
return Disposables.create(with: controlTarget.dispose)
}
.takeUntil(deallocated)
// ControlEvent其實(shí)也是一個(gè)特殊的可觀察序列
return ControlEvent(events: source)
}
即button的點(diǎn)擊事件處理的第一步,確實(shí)創(chuàng)建了一個(gè)Observable靶庙。同時(shí)我們要對(duì)點(diǎn)擊事件處理的代碼问畅,也確實(shí)是寫(xiě)在觀察者訂閱序列的時(shí)候,并且也必須得通過(guò)disposed(by: disposeBag)方法回收資源六荒。
RxSwift是怎么通過(guò)基本流程來(lái)實(shí)現(xiàn)事件響應(yīng)的
首先我們來(lái)分析护姆,在UIKit中點(diǎn)擊事件的響應(yīng)流程,即target-action模式
- 定義一個(gè)響應(yīng)函數(shù)
- 通過(guò) button.addTarget將響應(yīng)函數(shù)作為button的事件處理函數(shù)
然后我們注意到掏击,在rxswift的button.rx.tap的實(shí)現(xiàn)中卵皂,Observable的創(chuàng)建過(guò)程中,有下面這段代碼塊:
let controlTarget = ControlTarget(control: control, controlEvents: controlEvents) { _ in
observer.on(.next(()))
}
在ControlTarget類文件中我們會(huì)看到UIKit的target-action模式砚亭,并且可以知道當(dāng)點(diǎn)擊事件發(fā)生時(shí)就會(huì)執(zhí)行ControlTarget初始化時(shí)傳進(jìn)去的閉包灯变,即執(zhí)行 observer.on(.next(()))
通過(guò)以上分析我們知道,當(dāng)點(diǎn)擊事件發(fā)生時(shí)就會(huì)執(zhí)行 observer.on(.next(()))
捅膘,但是我們處理事件的業(yè)務(wù)卻是寫(xiě)在Observable對(duì)象的subscribe
函數(shù)的參數(shù)閉包下面添祸。
因此我們分析這兩個(gè)閉包是否有關(guān)系呢?
或者我們猜測(cè)他們肯定有關(guān)系,才能保證流程是正確的寻仗。
同時(shí)我們會(huì)有一個(gè)疑問(wèn)刃泌,observer是在哪里創(chuàng)建并且傳入到Observable中去的呢?
分析RxSwift的源碼署尤,可以發(fā)現(xiàn)
extension ObservableType {
// MARK: create
public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> {
return AnonymousObservable(subscribe)
}
}
final private class AnonymousObservable<Element>: Producer<Element> {
typealias SubscribeHandler = (AnyObserver<Element>) -> Disposable
let _subscribeHandler: SubscribeHandler
init(_ subscribeHandler: @escaping SubscribeHandler) {
self._subscribeHandler = subscribeHandler
}
override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
let subscription = sink.run(self)
return (sink: sink, subscription: subscription)
}
}
class Producer<Element> : Observable<Element> {
override init() {
super.init()
}
override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
if !CurrentThreadScheduler.isScheduleRequired {
// The returned disposable needs to release all references once it was disposed.
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
else {
return CurrentThreadScheduler.instance.schedule(()) { _ in
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
}
}
func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
rxAbstractMethod()
}
}
- Observable create方法會(huì)創(chuàng)建一個(gè)內(nèi)部私有類AnonymousObservable的對(duì)象
- AnonymousObservable繼承自Producer類耙替,而Producer實(shí)現(xiàn)了ObservableType協(xié)議要求的
subscribe
方法,subscribe方法會(huì)接收到一個(gè)觀察者observer曹体。 - 通過(guò)subscribe的參數(shù)俗扇,可以知道我們使用的訂閱函數(shù)和Producer的subscribe并不是同一個(gè)函數(shù)
然后分析我們觀察者訂閱可觀察序列時(shí)調(diào)用的subscribe函數(shù)
public func subscribe(onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)
-> Disposable {
let disposable: Disposable
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
#if DEBUG
let synchronizationTracker = SynchronizationTracker()
#endif
let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : []
// 這里創(chuàng)建了一個(gè)observer
let observer = AnonymousObserver<Element> { event in
#if DEBUG
synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { synchronizationTracker.unregister() }
#endif
switch event {
case .next(let value):
onNext?(value)
case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler(callStack, error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
}
發(fā)現(xiàn),原來(lái)觀察者是通過(guò)訂閱的時(shí)候創(chuàng)建的混坞,并且在return語(yǔ)句時(shí)通過(guò)self.asObservable().subscribe(observer)傳給Observable狐援,這個(gè)self應(yīng)該是AnonymousObservable的對(duì)象,這個(gè)subscribe即為Producer類定義的subscribe方法究孕。
至此啥酱,我們可以確定,observer.on(.next(()))
方法確實(shí)是調(diào)用的訂閱時(shí)subscribe的onNext閉包厨诸。
總結(jié)
Observer: onNext()
Observable -> AnonymousObservable -> Producer : subscribe(observer)
ObservableType: subscribe(onNext: ()->()), create() -> AnyAnonymousObservable
- Observable.create 可以拿到一個(gè)可觀察序列镶殷,并且,可以通過(guò)閉包參數(shù)observer來(lái)發(fā)送數(shù)據(jù)
- Observable.create 創(chuàng)建的Observable其實(shí)是AnonymousObservable類型的(Observable的創(chuàng)建方法還有其他的微酬,它們其實(shí)是生成了不同的ObservableType的實(shí)現(xiàn)類)绘趋,創(chuàng)建的各種Observable其實(shí)都是繼承自Producer
- 觀察者訂閱可觀察序列,其實(shí)是ObservableType協(xié)議的默認(rèn)實(shí)現(xiàn)颗管,并且我們只要提供處理數(shù)據(jù)的閉包就行陷遮,observer在ObservableType默認(rèn)實(shí)現(xiàn)的subscribe方法中就自動(dòng)創(chuàng)建,并且會(huì)將我們提供的閉包給到創(chuàng)建的observer
- ObservableType協(xié)議的默認(rèn)實(shí)現(xiàn)會(huì)將創(chuàng)建的observer傳遞給自己的實(shí)現(xiàn)類的對(duì)象
- Observable一旦發(fā)送數(shù)據(jù)垦江,observer就會(huì)執(zhí)行我們subscribe時(shí)提供的閉包