https://www.jianshu.com/p/1765f658200a 例子寫的很是好呢.
這是告別CSDN後第一次使用簡書寫IT類的博客,還在適應。最不適應的就是不能直接手輸markdown語法標記。(好像緣由是我沒有切換編輯器)java
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.react
-- Wikipediaexpress
以上解釋來自維基百科,在計算機領域,響應式編程是一個專一於數據流和變化傳遞的異步編程範式。這意味着可使用編程語言很容易地表示靜態(例如數組)或動態(例如事件發射器)數據流,而且在關聯的執行模型中,存在着可推斷的依賴關係,這個關係的存在有利於自動傳播與數據流有關的更改。編程
拋開大段大段的概念,咱們先搞清楚一件事情:什麼是編程範式?數組
通俗的說:編程是爲了解決問題,而解決問題能夠有多種視角和思路,其中具備普適性的模式被歸結爲範式。咱們常說的:「面向對象」,「面向過程」都是編程範式。markdown
響應式編程是一種從數據流和變化出發的解決問題的模式。因此要研究響應式編程,必定要牢記已經掌握的OO(面向對象,筆者妄斷你們OO的思想都是很根深蒂固了)來作對比,也必定要拋開OO避免鑽牛角尖。框架
在展開這個問題前,咱們先看一個故事,引自知乎:小故事異步
摘抄以下:async
老張愛喝茶,廢話不說,煮開水。編程語言
出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
1 老張把水壺放到火上,立等水開。(同步阻塞)
老張以爲本身有點傻2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)
老張仍是以爲本身有點傻,因而變高端了,買了把會響笛的那種水壺。水開以後,能大聲發出嘀~~~~的噪音。3 老張把響水壺放到火上,立等水開。(異步阻塞)
老張以爲這樣傻等意義不大4 老張把響水壺放到火上,去客廳看電視,水壺響以前再也不去看它了,響了再去拿壺。(異步非阻塞)
老張以爲本身聰明瞭。所謂同步異步,只是對於水壺而言。普通水壺,同步;響水壺,異步。雖然都能幹活,但響水壺能夠在本身完工以後,提示老張水開了。這是普通水壺所不能及的。同步只能讓調用者去輪詢本身(狀況2中),形成老張效率的低下。
所謂阻塞非阻塞,僅僅對於老張而言。立等的老張,阻塞;看電視的老張,非阻塞。狀況1和狀況3中老張就是阻塞的,媳婦喊他都不知道。雖然3中響水壺是異步的,可對於立等的老張沒有太大的意義。因此通常異步是配合非阻塞使用的,這樣才能發揮異步的效用。
上面這個小故事仍是有點問題,但基本能夠說明問題了。
響應,必定是對一個事件、一個信號(諸如此類的描述)產生了反應。響水壺的響應是什麼呢?水溫達到必定程度,水壺的反應是會響。水壺響了,聲音傳遞給老張,老張的反應是去關水壺。
再看普通水壺,水溫達到必定程度,水壺沒有反應,水的反應是冒氣泡,冒水霧。只是這個信號不太容易傳遞,要跑過來看,因此老張只能以輪訓的方式來辦事情,無法跑到一邊等通知。
對於兩個水壺而言,燒水都是阻塞的,水沒燒完就幹不了其餘的事情(好比說拿來砸胡桃???)
ok,回到咱們的問題:爲何是異步?
迴歸到本質回答這個問題:響應式編程,本質上是對數據流或某種變化所做出的反應,可是這個變化何時發生是未知的,因此他是一種基於異步、回調的方式在處理問題。
正如副標題,在網上搜索到的絕大多數的博客都會說着說着就在教你如何使用RxAndroid。各位,請記住如下幾點:
RxAndroid(或RxJava)是很優秀的響應式編程框架。
你並不是必定須要使用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,請容許我再問一個問題,如此簡介的代碼,您打算單獨用一個類來放嗎?
若是對於任何一個處理相似業務邏輯的rx代碼段都使用類來放,可能類數量會爆炸,並且這些類的命名看起來會很奇葩。若不這樣,您的業務實現類中將充斥諸如此類不精讀不敢肯定語義、容易被誤修改、不容易測試的代碼。面對這樣的代碼的時候只會是如履薄冰戰戰兢兢。
No,我只是反對濫用Rx,我同意對某些高度抽象的異步行爲使用Rx構建具備語義性的框架代碼,例如:編寫MVVM分層框架。反對對任何業務細節都去作「一切皆流」的無腦工做。畢竟:業務是須要逐漸迭代發展的,對於有測試代碼支撐的、同時有較強語義性的類,咱們泛讀代碼就能夠「聞絃歌而知雅意」,對於須要重構何處代碼,修改何處邏輯心中有數,而沒必要將「流」再反轉回「實際的相互關係」,再打亂,修改,再組織成流,再噁心下一次迭代,並且,最關鍵的是「你可能要從不少的流中找出這一個流」。