程序猿打Boss高級技能——Rx

對于函數(shù)響應(yīng)式編程(Functional Reactive Programming),本人第一次接觸到是在兩年前,當(dāng)時看到ReactiveCocoa框架對它一時不來電。直到最近抽時間學(xué)習(xí)了一下Swift 語言,對Swift版本的FRP 框架RxSwift 進(jìn)行了深入的學(xué)習(xí)。

1、背景

我們可愛的程序猿在開發(fā)的過程中,因為業(yè)務(wù)需求,在數(shù)據(jù)流處理或者是用戶操作的各個階段,總是避免不了創(chuàng)建許多臨時狀態(tài),用來判別、疏導(dǎo)程序的執(zhí)行順序。其中,在開發(fā)異步程序的時候,這種臨時狀態(tài)所帶來的問題尤為明顯。

舉個例子:我們經(jīng)常碰到像“鍵盤精靈”、“搜索引擎”這類異步的搜索功能。當(dāng)用戶輸入“0”的時候,程序就應(yīng)該實時的去請求相應(yīng)的結(jié)果集。這個時候,因為網(wǎng)絡(luò)的原因數(shù)據(jù)遲遲未能返回,不過用戶還在繼續(xù)輸入想要搜索的更加精準(zhǔn)的字符“01”、“012”等等,每一次的輸入變化邏輯上都要撤銷前一次的請求,再發(fā)送請求最新的結(jié)果集。到這里還不算復(fù)雜,那么,如果當(dāng)我們的請求失敗的時候,就需要編寫retry 重試邏輯,請求成功和失敗之間的需要維護(hù)一堆的臨時狀態(tài)和處理邏輯。

OMG!!! These will be driving me mad. 有木有?有木有更加簡單清晰一點(diǎn)方案來救救我吧?。?!

那么下面就讓我們來見證一下奇跡(Swift 代碼):

其中,searchTextField 是用戶輸入搜索字符的TextField 控件,而searchTextField.rx_text 就好像給這個控件鑿開了一個口子,當(dāng)用戶輸入字符的時候,字符就像從這個“口子”里流出來的水一樣,一滴、兩滴、三滴……

這個時候,如果不對水流做一些節(jié)制,那么就白白浪費(fèi)掉了。Throttle 操作函數(shù)就像在這個“口子”上裝了水龍頭一樣——開源節(jié)流,不隨意浪費(fèi)“資源”。這里的意思是:每次變化都停留了300毫秒后,打開水龍頭放水。

當(dāng)下一次擰開水龍頭放水時,如果流出來的字符和上一次一樣,這個時候重復(fù)發(fā)送請求的話,其實是沒有意義的。distinctUntilChanged 就是過濾去重的作用,不發(fā)送同前一次一樣的請求。

flatMapLatest 的Block 中拿到了放出來的“有效”字符串,程序執(zhí)行到這里才真正去發(fā)送API.getSearchResults(query) 網(wǎng)絡(luò)請求去搜索結(jié)果集。剛才說到的失敗retry 重試邏輯,在這里就只是一個簡單的Operator 操作,Rx 已經(jīng)幫我們處理好了如何retry。我們只需要關(guān)注搜索的結(jié)果集,對結(jié)果數(shù)據(jù)進(jìn)行展示處理救OK 了。

我們知道,臨時狀態(tài)一多就會使我們的代碼雜亂甚至難以維護(hù)。同樣的業(yè)務(wù)邏輯,這么簡短的幾行代碼,同時又幫助我們解決了常規(guī)開發(fā)思維中碰到的許多麻煩,而且它沒有任何附加的臨時狀態(tài)。

“這是什么鬼,本來要寫五百行代碼,現(xiàn)在十行都不到,簡直就是無視我的KPI?。。?!”。

這就是傳說中的函數(shù)響應(yīng)式編程(Functional Reactive Programming),市面上常用的語言都擁有它的身影(RxJS,RxJava,RxCpp,RxPhp,Rx.Net等等),作為一個編程思想的集合體,官方稱為ReactiveX(官網(wǎng):http://reactivex.io),簡稱Rx。

Rx 是觀察者模式(Observer Pattern)的典型應(yīng)用,所有的異步信息流都可以抽象為一個可觀察對象(Observable),需要使用信息流的對象抽象為觀察者(Observer)。Observer 根據(jù)需要向Observable 發(fā)起訂閱,即:Observable.subscribe(Observer)。當(dāng)Observable 有信息到來時,來自全世界的Observer 都能夠接收得到。

Rx 的目標(biāo)是讓異步和事件數(shù)據(jù)流操作更簡單。

引用:KVO observing, async operations and streams are all unified under abstraction of sequence. This is the reason why Rx is so simple, elegant and powerful.

2、Rx的優(yōu)點(diǎn)

1) 線程安全

數(shù)據(jù)是通過值拷貝的方式在線程中進(jìn)行傳遞——值傳遞,其他線程也有自己的數(shù)據(jù)Copy,互不牽扯。好比數(shù)學(xué)中函數(shù),指定傳入的參數(shù),也就確定了答案一樣“Data in and Data out”,這也就是為什么叫做函數(shù)式的由來。

2) 代碼更加簡潔精煉,開發(fā)效率顯著提高

正如前面的例子,簡單的調(diào)用幾個操作函數(shù),簡化了常規(guī)編程中許多臨時狀態(tài)造成的復(fù)雜邏輯,減少了大量bug的產(chǎn)生,是開發(fā)更加高效。第1、2點(diǎn)和Rx的目標(biāo)吻合。

3)代替異步操作,用Rx操作函數(shù)輕松處理(轉(zhuǎn)換、過濾、合并)

根據(jù)Rx異步操作的抽象概念(Observer Pattern),以下的異步操作都可以抽象成可觀察對象(Observable)和觀察者(Observer)。事實上,Rx已經(jīng)提供了這些類型的抽象,如Swift語言中,可以參考RxCocoa框架。

代理:Delegate

回調(diào):Block Callbacks

事件:Target Action

通知:Notifications

KVO

4) MVVM 模式最佳粘合劑,讓單元測試更得心應(yīng)手

我們知道MVVM 模式讓視圖控制器VC 的身板更加精致,VC 和VM 之間的責(zé)任邊界也非常明確:VM 負(fù)責(zé)數(shù)據(jù)處理&VC 負(fù)責(zé)數(shù)據(jù)展示。

現(xiàn)在,Rx 和 MVVM結(jié)合在一起,除了Bug 隨著臨時狀態(tài)大量減少外,單元測試也變的非常容易。Rx 測試框架RxTest提供了一組強(qiáng)大的模擬接口,可以模擬信息流,也就是可以模擬用戶操作,非常方便的開發(fā)單元測試程序。

3、Rx延伸方向思考

1) 各平臺接口用Rx 封裝(很多平臺&云服務(wù)已經(jīng)對外提供了Rx 接口)

2) 使用MVVM 開發(fā)模式,場景化包裝可重用VM 模塊

其中1是接口級(我們已經(jīng)實現(xiàn)),2是VM模塊級(包裝了業(yè)務(wù)模型,從UI分離出來)

3) 跨平臺開發(fā)

用JS 開發(fā)各平臺UI,使用Native 封裝Rx接口(互調(diào)性能問題?耦合性高)

界面布局和信息流(RxJS)邏輯用JS實現(xiàn)。Native 開發(fā)渲染Render 引擎(有點(diǎn)類似React Native)。

4、總結(jié)

看到如此簡單的幾行代碼就能實現(xiàn)原本復(fù)雜邏輯而正為之興奮不已的時候,有沒有感覺到像是獲得了另一種更加強(qiáng)大的高級技能?。?!

那么,我們靜下心來捋一捋:Rx之于我們程序員的重要性在于,當(dāng)PM為用戶場景化交互進(jìn)行激烈地討(si)論(bi)時,我們程序員(PG)又有了一種可選技能,而且“已然”對各種場景有了最有效的技能應(yīng)對——擁抱變化,成竹在胸

5、附錄

附上RxSwift中常用的一種可觀察對象(Just)源碼CSequence圖,幫助理解源代碼。

藍(lán)色背景的是繼承關(guān)系的Protocol 或父類,黃色背景的是實體對象類(左邊Observable,右邊Observer),當(dāng)可觀察對象被訂閱Observable.subscribe(Observer) 時,兩者之間的交互邏輯。

參考:

Rx官網(wǎng):http://reactivex.io

Rx可視化工具,幫助理解各種操作函數(shù) :http://rxmarbles.com/

Rx開源Github:https://github.com/Reactive-Extensions


本文作者:羅俊濤(點(diǎn)融黑幫),現(xiàn)任點(diǎn)融網(wǎng)高級移動iOS開發(fā)工程師。從最初的嵌入式研發(fā)到近幾年金融產(chǎn)品研發(fā),對金融產(chǎn)品有比較全面的認(rèn)識。一直認(rèn)為“能夠?qū)W⒂诩夹g(shù),翱翔于代碼的無邊天際”是一件無比幸福的事情。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,008評論 25 709
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,551評論 19 139
  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位,與響應(yīng)式編程作為結(jié)合使用的,對什么是操作、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,980評論 0 10
  • 引言 RxAndroid是一個開發(fā)庫、是一種代碼風(fēng)格、也是一種思維方式。 正如標(biāo)題所言,RxAndroid的特點(diǎn)是...
    藍(lán)灰_q閱讀 25,077評論 4 106
  • 那些相處時 讓我們感到舒服的人 他們的微笑令人陶醉 舉止讓人溫暖 沒有過不去的坎 沒有渡不過的劫 有些人的善意 就...
    劉思琳閱讀 286評論 0 2

友情鏈接更多精彩內(nèi)容