為什么要學(xué)RXSwift?
有產(chǎn)生這個(gè)疑問(wèn)的同學(xué)譬圣,請(qǐng)先看下圖
試問(wèn),這么牛逼
的框架不值得去研究一番嘛雄坪?厘熟??
(貼心奉上)點(diǎn)了我维哈,愛(ài)上我
決定要去做一件事绳姨,至少要知道原因,或者是需要一份動(dòng)力阔挠。RXSwift
官網(wǎng)上列舉了一些例子簡(jiǎn)單告訴了我們RXSwift
具備了哪些能力飘庄,比如說(shuō):
- 它可以統(tǒng)一處理
Delegate
,KVO
,Notification
- 它可以綁定UI
- 方便網(wǎng)絡(luò)請(qǐng)求的處理
等等一系列能力......
但這些也只是描述了可以用RXSwift
可以來(lái)做什么,而我們更關(guān)注的是為什么要選擇RXSwift
?
關(guān)于這一點(diǎn)我們需要分析下GUI 編程的本質(zhì)
GUI
可以抽象為視圖和數(shù)據(jù)的結(jié)合
視圖負(fù)責(zé)兩件事:展示和交互购撼,而展示什么由數(shù)據(jù)決定跪削!
上圖可以看到RxSwift
可以在UniDirectional Data Flow
的各個(gè)階段都發(fā)揮作用,從而讓Data 的處理和流動(dòng)更加簡(jiǎn)潔和清晰迂求!
具體解釋如下:
- 通過(guò)對(duì)
RxCocoa
的各種回調(diào)進(jìn)行統(tǒng)一處理碾盐,方便了「Interact」
的處理。 - 通過(guò)對(duì)
Observable
的transform
和composite
揩局,方便了「Action」
的生成(比如使用throttle
來(lái)壓縮Action
)毫玖。 - 通過(guò)對(duì)網(wǎng)絡(luò)請(qǐng)求以及其他異步數(shù)據(jù)的獲取進(jìn)行
Observable
封裝,方便了異步數(shù)據(jù)的處理。 - 通過(guò)
RxCocoa
的binding
孕豹,方便了數(shù)據(jù)的渲染涩盾。
綜上我們能看到
RxCocoa
規(guī)范了數(shù)據(jù)流,RxSwift
為數(shù)據(jù)的處理提供了方便励背,這兩個(gè)類(lèi)庫(kù)的結(jié)合春霍,可以產(chǎn)生清晰的架構(gòu)和易維護(hù)的代碼
RXSwift所為何物?
在說(shuō)RxSwift
之前叶眉,先來(lái)說(shuō)下Rx
址儒, ReactiveX 是一種編程模型,最初由微軟開(kāi)發(fā)衅疙,結(jié)合了觀察者模式莲趣、迭代器模式和函數(shù)式編程的精華,來(lái)更方便地處理異步數(shù)據(jù)流饱溢。其中最重要的一個(gè)概念是 Observable
喧伞。
在這里有個(gè)比較好的例子幫助理解這個(gè)Observable
“舉個(gè)簡(jiǎn)單的例子,當(dāng)別人在跟你說(shuō)話(huà)時(shí)绩郎,你就是那個(gè)觀察者潘鲫,別人就是那個(gè) Observable,它有幾個(gè)特點(diǎn):
- 可能會(huì)不斷地跟你說(shuō)話(huà)肋杖。(
onNext:
)- 可能會(huì)說(shuō)錯(cuò)話(huà)溉仑。(
onError:
)- 結(jié)束會(huì)說(shuō)話(huà)。(
onCompleted
)你在聽(tīng)到對(duì)方說(shuō)的話(huà)后状植,也可以有幾種反應(yīng):
- 根據(jù)說(shuō)的話(huà)浊竟,做相應(yīng)的事,比如對(duì)方讓你借本書(shū)給他津畸。(
subscribe
)- 把對(duì)方說(shuō)的話(huà)振定,加工下再傳達(dá)給其他人,比如對(duì)方說(shuō)小張好像不太舒服肉拓,你傳達(dá)給其他人時(shí)就變成了小張失戀了吩案。(
map:
)- 參考其他人說(shuō)的話(huà)再做處理,比如 A 說(shuō)某家店很好吃帝簇,B 說(shuō)某家店一般般徘郭,你需要結(jié)合兩個(gè)人的意見(jiàn)再做定奪。(
zip:
)”
在這里核心是當(dāng)數(shù)據(jù)有變化時(shí)丧肴,能夠立刻知曉残揉,并且通過(guò)組合和轉(zhuǎn)換后,可以即時(shí)作出響應(yīng)芋浮。
RXSwift工作流抱环?
在了解了RXSwift后壳快,我們自然而然的就會(huì)想它具體的工作流程是什么呢?
其實(shí)大致可以分為這么幾個(gè)階段:
-
先把
Native Object
變成Observable
| -
通過(guò)
Observable
內(nèi)置的各種強(qiáng)大的轉(zhuǎn)換和組合能力變成新的Observable
| - 最后消費(fèi)新的
Observable
的數(shù)據(jù)
可以參考下圖來(lái)理解:
Native Object -> Observable
-
rx extension
可以說(shuō)“萬(wàn)物皆可RX”镇草,直接上圖
看到這里眶痰,無(wú)需多言了吧。梯啤。
Observable.create
通過(guò)這個(gè)方法竖伯,可以將 Native object
包裝成 Observable
public static func create(_ subscribe: @escaping (AnyObserver<E>) -> Disposable) -> Observable<E> {
return AnonymousObservable(subscribe)
}
-
Variable()
Variable(value)
可以把value
變成一個(gè)Observable
我們可以點(diǎn)擊到它里面看一下
public final class Variable<Element> {
public typealias E = Element
private let _subject: BehaviorSubject<Element>
private var _lock = SpinLock()
// state
private var _value: E
#if DEBUG
fileprivate let _synchronizationTracker = SynchronizationTracker()
#endif
/// Gets or sets current value of variable.
///
/// Whenever a new value is set, all the observers are notified of the change.
///
/// Even if the newly set value is same as the old value, observers are still notified for change.
public var value: E {
get {
self._lock.lock(); defer { self._lock.unlock() }
return self._value
}
set(newValue) {
#if DEBUG
self._synchronizationTracker.register(synchronizationErrorMessage: .variable)
defer { self._synchronizationTracker.unregister() }
#endif
self._lock.lock()
self._value = newValue
self._lock.unlock()
self._subject.on(.next(newValue))
}
}
/// Initializes variable with initial value.
///
/// - parameter value: Initial variable value.
public init(_ value: Element) {
#if DEBUG
DeprecationWarner.warnIfNeeded(.variable)
#endif
self._value = value
self._subject = BehaviorSubject(value: value)
}
/// - returns: Canonical interface for push style sequence
public func asObservable() -> Observable<E> {
return self._subject
}
deinit {
self._subject.on(.completed)
}
}
就會(huì)發(fā)現(xiàn)是它通過(guò) subject
來(lái)做的,大意是把 value
存到一個(gè)內(nèi)部變量_value
里因宇,當(dāng)調(diào)用 value
方法時(shí)七婴,先更新_value
值,然后調(diào)用內(nèi)部的_subject.on(.next(newValue))
方法告知 subscriber
- Subject
Subject
簡(jiǎn)單說(shuō)是一個(gè)可以主動(dòng)發(fā)射數(shù)據(jù)的Observable
察滑,多了 onNext(value), onError(error), ‘onCompleted’
方法!
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("AAA")
subject.onNext("BBB")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("??????")
subject.onNext("??????")
Subject
還是建議少用打厘,雖然官方并沒(méi)有提及,但因?yàn)樵谝郧笆褂肦AC的時(shí)候贺辰,Subject
因其本身功能太過(guò)強(qiáng)大户盯,不好控制,成了一個(gè)不太推薦使用的功能饲化,
- Observable -> New Observable
Observable
----(修改/過(guò)濾/組合等操作)---->New Observable
換言之先舷,Observable
可以隨心所欲構(gòu)造自己想要的數(shù)據(jù)~!
Combine
Combine
就是把多個(gè)Observable
組合起來(lái)使用Transform
對(duì)一個(gè)Observable
的數(shù)值做一些小改動(dòng)滓侍,產(chǎn)出新的值,依是Observable
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.map { $0 * $0 }
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
-
Filter
Filter
的作用是對(duì)Observable
傳過(guò)來(lái)的數(shù)據(jù)進(jìn)行過(guò)濾牲芋,只有符合條件的才有資格被subscribe
結(jié)語(yǔ)
上面只是簡(jiǎn)單介紹了RXSwift
相關(guān)的一些基本概念撩笆,其實(shí)這些如果理清楚了,你會(huì)發(fā)現(xiàn)RXSwift
并不難(尤其是具備RAC開(kāi)發(fā)經(jīng)驗(yàn)的)缸浦,要習(xí)慣多去從Observable
的角度分析思考問(wèn)題夕冲,慢慢的就會(huì)領(lǐng)略到函數(shù)響應(yīng)式編程的真正魅力了,同時(shí)自身的抽象能力和代碼可讀性都會(huì)有提升裂逐。
學(xué)習(xí)技術(shù)我個(gè)人覺(jué)得掌握其核心思想最重要歹鱼,因?yàn)樗强梢蕴嵘銈€(gè)人認(rèn)知能力的~!
這不僅僅可以幫助你解決技術(shù)問(wèn)題卜高,也可以在你生活中遇到問(wèn)題時(shí)弥姻,提供解決思路~!