淺談響應(yīng)式編程(Reactive Programming)

這是告別CSDN后第一次使用簡書寫IT類的博客阳懂,還在適應(yīng)。最不適應(yīng)的就是不能直接手輸markdown語法標記。(好像原因是我沒有切換編輯器)

什么是響應(yīng)式編程(Reactive Programming)

In computing, reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. This means that it becomes possible to express static (e.g. arrays) or dynamic (e.g. event emitters) data streams with ease via the employed programming language(s), and that an inferred dependency within the associated execution model exists, which facilitates the automatic propagation of the change involved with data flow.

-- Wikipedia

以上解釋來自維基百科,在計算機領(lǐng)域,響應(yīng)式編程是一個專注于數(shù)據(jù)流和變化傳遞的異步編程范式朴读。這意味著可以使用編程語言很容易地表示靜態(tài)(例如數(shù)組)或動態(tài)(例如事件發(fā)射器)數(shù)據(jù)流,并且在關(guān)聯(lián)的執(zhí)行模型中走趋,存在著可推斷的依賴關(guān)系衅金,這個關(guān)系的存在有利于自動傳播與數(shù)據(jù)流有關(guān)的更改。

拋開大段大段的概念,我們先搞清楚一件事情:什么是編程范式氮唯?

通俗的說:編程是為了解決問題鉴吹,而解決問題可以有多種視角和思路,其中具有普適性的模式被歸結(jié)為范式惩琉。我們常說的:“面向?qū)ο蟆倍估懊嫦蜻^程”都是編程范式。

響應(yīng)式編程是一種從數(shù)據(jù)流和變化出發(fā)的解決問題的模式瞒渠。所以要研究響應(yīng)式編程良蒸,一定要牢記已經(jīng)掌握的OO(面向?qū)ο螅P者妄斷大家OO的思想都是很根深蒂固了)來做對比伍玖,也一定要拋開OO避免鉆牛角尖嫩痰。

為什么是異步?

在展開這個問題前窍箍,我們先看一個故事串纺,引自知乎:小故事

摘抄如下:

老張愛喝茶,廢話不說椰棘,煮開水造垛。

出場人物:老張,水壺兩把(普通水壺晰搀,簡稱水壺;會響的水壺办斑,簡稱響水壺)外恕。

1 老張把水壺放到火上,立等水開乡翅。(同步阻塞)
老張覺得自己有點傻

2 老張把水壺放到火上鳞疲,去客廳看電視,時不時去廚房看看水開沒有蠕蚜。(同步非阻塞)
老張還是覺得自己有點傻尚洽,于是變高端了,買了把會響笛的那種水壺靶累。水開之后腺毫,能大聲發(fā)出嘀~~~~的噪音。

3 老張把響水壺放到火上挣柬,立等水開潮酒。(異步阻塞)
老張覺得這樣傻等意義不大

4 老張把響水壺放到火上,去客廳看電視邪蛔,水壺響之前不再去看它了急黎,響了再去拿壺。(異步非阻塞)
老張覺得自己聰明了。

所謂同步異步勃教,只是對于水壺而言淤击。普通水壺,同步故源;響水壺污抬,異步。雖然都能干活心软,但響水壺可以在自己完工之后壕吹,提示老張水開了。這是普通水壺所不能及的删铃。同步只能讓調(diào)用者去輪詢自己(情況2中)耳贬,造成老張效率的低下。

所謂阻塞非阻塞猎唁,僅僅對于老張而言咒劲。立等的老張,阻塞诫隅;看電視的老張腐魂,非阻塞。情況1和情況3中老張就是阻塞的逐纬,媳婦喊他都不知道蛔屹。雖然3中響水壺是異步的,可對于立等的老張沒有太大的意義豁生。所以一般異步是配合非阻塞使用的兔毒,這樣才能發(fā)揮異步的效用。

上面這個小故事還是有點問題甸箱,但基本可以說明問題了育叁。

響應(yīng),一定是對一個事件芍殖、一個信號(諸如此類的描述)產(chǎn)生了反應(yīng)豪嗽。響水壺的響應(yīng)是什么呢?水溫達到一定程度,水壺的反應(yīng)是會響豌骏。水壺響了龟梦,聲音傳遞給老張,老張的反應(yīng)是去關(guān)水壺肯适。

再看普通水壺变秦,水溫達到一定程度,水壺沒有反應(yīng)框舔,水的反應(yīng)是冒氣泡蹦玫,冒水霧赎婚。只是這個信號不太容易傳遞,要跑過來看樱溉,所以老張只能以輪訓的方式來辦事情挣输,沒法跑到一邊等通知。

對于兩個水壺而言福贞,燒水都是阻塞的撩嚼,水沒燒完就干不了其他的事情(比如說拿來砸胡桃?挖帘?完丽?)

ok,回到我們的問題:為什么是異步?

回歸到本質(zhì)回答這個問題:響應(yīng)式編程拇舀,本質(zhì)上是對數(shù)據(jù)流或某種變化所作出的反應(yīng)逻族,但是這個變化什么時候發(fā)生是未知的,所以他是一種基于異步骄崩、回調(diào)的方式在處理問題。

怪圈:似乎絕大多數(shù)博客說著說著就開始講解RxAndroid

正如副標題要拂,在網(wǎng)上搜索到的絕大多數(shù)的博客都會說著說著就在教你如何使用RxAndroid。各位脱惰,請記住以下幾點:

  • RxAndroid(或RxJava)是很優(yōu)秀的響應(yīng)式編程框架。

  • 你并非一定需要使用RxAndroid拉一。

  • RxAndroid并不像那些博客里面說的那樣會讓你的代碼變得更可讀彻况。

這里我直接進入第三點。取用扔物線推薦RxJava中的例子:如下這段代碼:

Observable.from(folders)
.flatMap((Func1) (folder) -> { Observable.from(file.listFiles()) }) 
.filter((Func1) (file) -> { file.getName().endsWith(".png") }) 
.map((Func1) (file) -> { getBitmapFromFile(file) })
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) 
.subscribe((Action1) (bitmap) -> { imageCollectorView.addImage(bitmap) });

就這段代碼,是否需要從上到下仔細閱讀一遍之后才能才會知道他的意圖良蛮?

甚至,為了精讀代碼决瞳,他可能是這樣:

Observable.from(folders)
    .flatMap(new Func1<File, Observable<File>>() {
        @Override
        public Observable<File> call(File file) {
            return Observable.from(file.listFiles());
        }
    })
    .filter(new Func1<File, Boolean>() {
        @Override
        public Boolean call(File file) {
            return file.getName().endsWith(".png");
        }
    })
    .map(new Func1<File, Bitmap>() {
        @Override
        public Bitmap call(File file) {
            return getBitmapFromFile(file);
        }
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Bitmap>() {
        @Override
        public void call(Bitmap bitmap) {
            imageCollectorView.addImage(bitmap);
        }
    });

ok,請允許我再問一個問題货徙,如此簡介的代碼,您打算單獨用一個類來放嗎皮胡?

如果對于任何一個處理類似業(yè)務(wù)邏輯的rx代碼段都使用類來放痴颊,可能類數(shù)量會爆炸屡贺,而且這些類的命名看起來會很奇葩锌杀。若不這樣泻仙,您的業(yè)務(wù)實現(xiàn)類中將充斥諸如此類不精讀不敢確定語義、容易被誤修改突想、不容易測試的代碼。面對這樣的代碼的時候只會是如履薄冰戰(zhàn)戰(zhàn)兢兢猾担。

我是在反對使用RxAndroid嗎刺下?

No,我只是反對濫用Rx怠李,我贊成對某些高度抽象的異步行為使用Rx構(gòu)建具有語義性的框架代碼,例如:編寫MVVM分層框架夷蚊。反對對任何業(yè)務(wù)細節(jié)都去做“一切皆流”的無腦工作髓介。畢竟:業(yè)務(wù)是需要逐漸迭代發(fā)展的,對于有測試代碼支撐的唐础、同時有較強語義性的類,我們泛讀代碼就可以“聞弦歌而知雅意”呀邢,對于需要重構(gòu)何處代碼豹绪,修改何處邏輯心中有數(shù)价淌,而不必將“流”再反轉(zhuǎn)回“實際的相互關(guān)系”瞒津,再打亂,修改病毡,再組織成流屁柏,再惡心下一次迭代有送,而且功戚,最關(guān)鍵的是“你可能要從很多的流中找出這一個流”。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末届宠,一起剝皮案震驚了整個濱河市乘粒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灯萍,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齿风,死亡現(xiàn)場離奇詭異绑洛,居然都是意外死亡,警方通過查閱死者的電腦和手機脸候,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門绑蔫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人配深,你說我怎么就攤上這事⌒皆ⅲ” “怎么了澜共?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵锥腻,是天一觀的道長。 經(jīng)常有香客問我京革,道長,這世上最難降的妖魔是什么匹摇? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任廊勃,我火速辦了婚禮懈贺,結(jié)果婚禮上坡垫,老公的妹妹穿的比我還像新娘。我一直安慰自己堡妒,他們只是感情好溉卓,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伏尼,像睡著了一般西疤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上代赁,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音徒役,去河邊找鬼窖壕。 笑死,一個胖子當著我的面吹牛瞻讽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晌砾,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼烦磁,長吁一口氣:“原來是場噩夢啊……” “哼哼勇!你這毒婦竟也來了呕乎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤帝璧,失蹤者是張志新(化名)和其女友劉穎逐虚,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叭爱,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡买雾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗤军。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晃危。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖僚饭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情史飞,我是刑警寧澤摊沉,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站贪薪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏竣稽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望庞萍。 院中可真熱鬧,春花似錦钝计、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荣德,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鲤拿,已是汗流浹背署咽。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宁否,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓异剥,卻偏偏與公主長得像絮重,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子青伤,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一.非阻塞和異步 借用知乎用戶嚴肅的回答在此總結(jié)下狠角,同步和異步是針對消息通信機制,同步代表一個client發(fā)出一個...
    Daniel_adu閱讀 1,827評論 0 8
  • 摘自廖雪峰教程 在IO編程一節(jié)中姨蟋,我們已經(jīng)知道,CPU的速度遠遠快于磁盤眼溶、網(wǎng)絡(luò)等IO。在一個線程中堂飞,CPU執(zhí)行代碼...
    rick_z閱讀 387評論 0 1
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 自打考上研究生就不停有學弟學妹通過各種途徑問我一些考研的問題绰筛。問的人多了,有了一點有趣的發(fā)現(xiàn)衡蚂。重點大學的小孩兒問的...
    笨鳥你要飛閱讀 397評論 0 0
  • 客廳里的電視機正在播放電影《超人》薄榛,大概講的是,一個外太空來的孩子掉到了地球敞恋,他生來就用大力,四五歲時便可輕易地舉...
    林泉兒閱讀 478評論 0 0