對(duì)MVP、Flux和RxAndroid框架的理解和選擇

為什么要使用框架

使用框架帘靡,是為了提高生產(chǎn)效率知给。

什么是生產(chǎn)效率?

上學(xué)的時(shí)候描姚,導(dǎo)師曾說:我以前上學(xué)那會(huì)兒涩赢,什么都得自己寫,別的不說轰胁,光把界面畫出來就夠發(fā)表篇論文了谒主,哪像你們現(xiàn)在,拿個(gè)鼠標(biāo)拖幾下就能弄出界面來赃阀。

這就是生產(chǎn)效率霎肯。

為什么使用框架能提高生產(chǎn)效率?

做過軟件的人都知道榛斯,我們開發(fā)一個(gè)軟件观游,其實(shí)就是把現(xiàn)實(shí)中的業(yè)務(wù)映射到軟件中去,這是一個(gè)對(duì)現(xiàn)實(shí)去做軟件建模驮俗,去做代碼實(shí)現(xiàn)的過程懂缕,而現(xiàn)實(shí)又是極度復(fù)雜的,做工程的基本常識(shí)是王凑,越復(fù)雜的東西風(fēng)險(xiǎn)就越高搪柑,所以軟件開發(fā)是充滿未知風(fēng)險(xiǎn)的聋丝,面對(duì)未知風(fēng)險(xiǎn),我們是茫然且恐懼的工碾,在茫然之下弱睦,我們最直接的反應(yīng)是:這種事一般要怎樣做,有什么經(jīng)驗(yàn)渊额,有沒有什么套路况木。

框架就是這樣一種套路,因?yàn)樗呀?jīng)通過某種范式旬迹,完成了對(duì)業(yè)務(wù)的解析火惊、映射和分層,在充滿未知的軟件開發(fā)中奔垦,框架的存在使開發(fā)有一定規(guī)矩可循屹耐,使常見的問題容易得到解決,使開發(fā)人員更專注于具體業(yè)務(wù)宴倍。

一般來說张症,使用框架有這樣幾點(diǎn)好處:

1、加快開發(fā)速度鸵贬。很多框架會(huì)幫你實(shí)現(xiàn)一些通用的、偏底層的實(shí)現(xiàn)脖捻、例如用IDE繪制軟件界面阔逼、用Hibernate讀寫數(shù)據(jù)庫、用EventBus傳遞事件地沮、用HttpClient處理網(wǎng)絡(luò)請(qǐng)求等(Android開發(fā)的框架會(huì)更多一些)嗜浮,除非是特殊的環(huán)境或有特別的訴求,否則沒有開發(fā)者愿意花費(fèi)大量的時(shí)間和精力摩疑,自己再造一遍輪子危融。

2、降低開發(fā)風(fēng)險(xiǎn)雷袋。還是造輪子的問題吉殃,每個(gè)輪子都會(huì)有缺陷,但是大家都在用的輪子楷怒,相對(duì)更加可靠蛋勺,發(fā)現(xiàn)缺陷也容易及時(shí)得到修復(fù)。

3鸠删、方便團(tuán)隊(duì)協(xié)作抱完。一般情況下,軟件開發(fā)都是團(tuán)隊(duì)行為刃泡,團(tuán)隊(duì)開發(fā)就要求在成員之間協(xié)調(diào)一致地并行工作巧娱,這就要求接口一致碉怔、風(fēng)格一致等,這會(huì)帶來很多管理上的問題禁添,而使用框架能較好地輔助這一點(diǎn)撮胧。

4、框架本身的優(yōu)勢上荡。每個(gè)框架的出現(xiàn)都是為了解決某些問題趴樱,像我們今天要討論的MVP、Flux和RxAndroid酪捡,都是為了解決日益復(fù)雜的業(yè)務(wù)邏輯導(dǎo)致軟件不可控的問題叁征,MVP的思路是“挪”,在MVC的基礎(chǔ)上把業(yè)務(wù)邏輯從View中挪走逛薇;Flux的思路是“單向流”捺疼,用嚴(yán)格的單向數(shù)據(jù)流去實(shí)現(xiàn)比較容易跟蹤檢測的邏輯結(jié)構(gòu);RxAndroid的思路則是“鏈?zhǔn)竭壿嫛庇婪#煤瘮?shù)反應(yīng)式編程的思想把邏輯啤呼、代碼和線程統(tǒng)統(tǒng)簡化為一條鏈?zhǔn)秸{(diào)用。

MVP

關(guān)于MVP的經(jīng)典表述可以參考Google開源項(xiàng)目Android Architecture Blueprints呢袱。

MVP想解決的問題是官扣,Google原來為Android準(zhǔn)備的MVC分層架構(gòu)中,C的存在極其薄弱羞福,存在嚴(yán)重的Activity膨脹的問題惕蹄,在很多開發(fā)中,Activity既是顯示界面治专,又是業(yè)務(wù)邏輯卖陵,從一開始就沒有分散職能,Activity會(huì)隨著業(yè)務(wù)的變化急速膨脹张峰,邏輯膨脹泪蔫,代碼膨脹,文件膨脹喘批,長期連續(xù)迭代下來撩荣,一個(gè)Activity的代碼很容易拖到幾千行甚至上萬行,代碼的復(fù)用性谤祖、可讀性和可維護(hù)性都變得非常糟糕婿滓。

膨脹的Activity

這種情況下,一個(gè)比較合理的思路就是“挪”粥喜,把業(yè)務(wù)邏輯從Activity中挪出來凸主,挪到Presenter中去,讓Activity回歸View的角色额湘,從此Presenter專注于業(yè)務(wù)卿吐,View專注于顯示旁舰。業(yè)務(wù)邏輯不再受Activity生命周期的影響,Activity也擺脫了業(yè)務(wù)邏輯無法復(fù)用的囧境嗡官。

用MVP對(duì)Activity瘦身

“挪”業(yè)務(wù)邏輯的MVP箭窜,基本解決了Activity膨脹的問題,View層變得相對(duì)簡單而安全了衍腥,而Presenter層中的業(yè)務(wù)邏輯磺樱,也比較容易做單元測試,做代碼復(fù)用婆咸,做進(jìn)一步的抽象和分離竹捉。

但是MVP中的業(yè)務(wù)邏輯仍然復(fù)雜,而且邏輯流和數(shù)據(jù)流基本處于只要不出bug尚骄,就可以放任自流的狀態(tài)块差,體現(xiàn)在業(yè)務(wù)邏輯上就是無數(shù)錯(cuò)綜交叉的業(yè)務(wù)線,體現(xiàn)在業(yè)務(wù)數(shù)據(jù)(Model)上就是無數(shù)的調(diào)用入口倔丈,長期運(yùn)轉(zhuǎn)下來憨闰,會(huì)發(fā)現(xiàn)越復(fù)雜的業(yè)務(wù)就越難以追蹤邏輯運(yùn)轉(zhuǎn)和數(shù)據(jù)狀態(tài),對(duì)軟件的維護(hù)擴(kuò)展非常不利需五。

MVP的業(yè)務(wù)邏輯

也就是說鹉动,MVP需要一個(gè)狀態(tài)管理工具,用來督促開發(fā)者按照一定規(guī)律處理狀態(tài)的讀寫宏邮,避免代碼變成一團(tuán)亂麻训裆。

Flux

關(guān)于Flux的經(jīng)典內(nèi)容可以參考Facebook的移動(dòng)架構(gòu)Android Flux

Flux試圖用“單向流”去實(shí)現(xiàn)狀態(tài)管理,它是一個(gè)單向綁定的單向數(shù)據(jù)流結(jié)構(gòu)蜀铲,一般我們看到的圖是這樣子的:

Flux結(jié)構(gòu)

Flux是一個(gè)單向環(huán),它實(shí)現(xiàn)業(yè)務(wù)的基本流程如下:

1属百、View響應(yīng)操作并創(chuàng)建對(duì)應(yīng)的Action

2记劝、Action調(diào)用單例的Dispatcher去統(tǒng)一處理所有請(qǐng)求

3、Dispatcher持有所有Store對(duì)象族扰,通過回調(diào)讓Store處理數(shù)據(jù)

4厌丑、Store處理數(shù)據(jù)后,發(fā)出事件(EventBus)通知View更新解密

5渔呵、View接收Store的事件后怒竿,刷新頁面

上面的圖并不能表現(xiàn)Dispatcher的中心作用,我們可以看這個(gè)圖:

復(fù)雜的Flux

可以看到扩氢,F(xiàn)lux實(shí)際上比MVP更啰嗦耕驰,要?jiǎng)?chuàng)建更多的對(duì)象,使用更多的訂閱和回調(diào)录豺,依賴EventBus去刷新頁面...

但是朦肘,F(xiàn)lux能把所有的業(yè)務(wù)都引流到一個(gè)Dispatcher單例中處理饭弓,這實(shí)際上建立了一種機(jī)制,這種機(jī)制能在同一個(gè)地方查詢狀態(tài)媒抠、改變狀態(tài)弟断、傳播狀態(tài)的變化,這就是MVP缺少的那種狀態(tài)管理工具趴生。

在這種機(jī)制下阀趴,所有的業(yè)務(wù)都是從某處開始并進(jìn)入Dispatcher,再離開Dispatcher去往某處結(jié)束苍匆,中間不可能有循環(huán)刘急,每條業(yè)務(wù)邏輯都只朝著終點(diǎn)方向運(yùn)行,這就實(shí)現(xiàn)了Flux“單向流”的思想锉桑,這就是單向數(shù)據(jù)流排霉。

單向數(shù)據(jù)流對(duì)軟件開發(fā)來說,意味著什么呢:

單向數(shù)據(jù)流

如上圖所示民轴,單向數(shù)據(jù)流攻柠,意味著業(yè)務(wù)邏輯得到了有效的管理,我們可以很清楚地知道每條業(yè)務(wù)線上會(huì)發(fā)生什么后裸,不會(huì)發(fā)生什么瑰钮,軟件的狀態(tài)和行為變得容易預(yù)測,代碼的可讀性和可預(yù)測性得到提高微驶,業(yè)務(wù)流程得以簡化浪谴,容易排除錯(cuò)誤,這給開發(fā)和維護(hù)帶來了極大的便利因苹。

Flux當(dāng)然也有問題苟耻,他太啰嗦,代碼復(fù)用太差扶檐,會(huì)有嚴(yán)重的action類膨脹問題凶杖。感興趣的開發(fā)者可以再去了解一下相對(duì)簡潔許多的Redux,目前主要在web開發(fā)中和React一起使用款筑,對(duì)Redux的介紹可以參考Redux中文文檔

RxAndroid

RxAndroid其實(shí)就是在Android中使用RxJava智蝠,詳細(xì)內(nèi)容可以參考給 Android 開發(fā)者的 RxJava 詳解

RxJava 是個(gè)了不起的工具,它使代碼的編寫和維護(hù)更加容易奈梳,而且更少出錯(cuò)杈湾,它的思路和MVP/Flux完全不同,如果說MVP/Flux關(guān)注的是類的分層和分工攘须,那么RxJava關(guān)注的就是純粹的業(yè)務(wù)邏輯鏈條漆撞。

RxJava的不同

RxJava通過訂閱事件驅(qū)動(dòng)的鏈?zhǔn)竭壿嬚{(diào)用,把復(fù)雜的異步邏輯維持成為一條簡單的鏈?zhǔn)浇Y(jié)構(gòu),來保持邏輯和代碼上的簡潔叫挟,這也使業(yè)界普遍認(rèn)為Rx編程屬于“函數(shù)響應(yīng)式編程(FRP)”艰匙,因?yàn)樗孟癫辉僖蕾囉谕ㄟ^面向?qū)ο螅∣O)的設(shè)計(jì)來解決問題,而是通過 “鏈?zhǔn)健钡乃季S方式抹恳,實(shí)現(xiàn)基于訂閱事件驅(qū)動(dòng)的簡潔的鏈?zhǔn)秸{(diào)用员凝,訂閱事件驅(qū)動(dòng)的基本思想如下:

訂閱事件驅(qū)動(dòng)

用被觀察者去發(fā)出事件,在觀察者中響應(yīng)事件奋献,形成異常簡潔的邏輯鏈條健霹,這種簡潔即是RxJava的魅力和優(yōu)勢所在。

一段RxJava的典型代碼是這樣的:

RxAndroid典型代碼

我們看到瓶蚂,所有的事情都在同一個(gè)鏈?zhǔn)秸{(diào)用里完成了糖埋,其中的訂閱和事件我們都不陌生,這也不是它保持簡潔的秘訣窃这,RxJava保持簡潔的秘訣在于鏈?zhǔn)秸{(diào)用瞳别,而鏈?zhǔn)秸{(diào)用的秘訣在于,每次邏輯調(diào)用后返回的對(duì)象杭攻,都是自己或自己的同類祟敛,并包含了繼續(xù)鏈?zhǔn)秸{(diào)用的方法。

鏈?zhǔn)秸{(diào)用

通過把復(fù)雜的業(yè)務(wù)維持成一條簡單的鏈?zhǔn)浇Y(jié)構(gòu)兆解,保持邏輯和代碼上的簡潔馆铁,這種做法的好處是顯而易見的,簡潔锅睛、優(yōu)雅埠巨、高效,而且現(xiàn)實(shí)中的業(yè)務(wù)線幾乎可以照葫蘆畫瓢地映射為代碼中的邏輯鏈现拒。

當(dāng)然RxJava也有他的問題辣垒,就是對(duì)代碼的掌控變?nèi)趿恕D馨褟?fù)雜問題用簡單形式表達(dá)出來當(dāng)然很了不起印蔬,但是復(fù)雜邏輯被表達(dá)為簡單鏈條后乍构,一方面擺脫了臃腫的代碼,另一方面卻因?yàn)榇a邏輯過于緊湊扛点,給排查故障帶來了障礙,比如說新手常犯的一個(gè)錯(cuò)誤是岂丘,忘記將網(wǎng)絡(luò)請(qǐng)求分配到異步線程去工作陵究,而默認(rèn)搭配的Retrofit網(wǎng)絡(luò)框架是無法在Android主線程上工作的,整條業(yè)務(wù)鏈從一開始就中斷了奥帘,但開發(fā)者能看到的直接反饋是業(yè)務(wù)鏈的結(jié)尾沒有輸出铜邮,很難精確定位到故障點(diǎn),只好對(duì)整條鏈路進(jìn)行檢查,這對(duì)開發(fā)和維護(hù)也是不利的松蒜。

感興趣的開發(fā)者也可以去閱讀我以前寫的文章RxAndroid使用初探—簡潔扔茅、優(yōu)雅、高效

如何選擇

在框架的選擇上秸苗,沒有最好的框架召娜,只有最合適的框架,特別是很多框架只是一種編程思想惊楼,你很難說自己在編程時(shí)會(huì)特意使用某種思想玖瘸,又特意不使用某種思想,就像前些年熱炒的設(shè)計(jì)模式一樣檀咙,不要為了使用而使用雅倒,能恰到好處地需要解決你的問題,就是適合你的弧可。

更詳細(xì)點(diǎn)說蔑匣,使用框架的問題不僅在于如何把框架應(yīng)用到你的項(xiàng)目中,也在于如何在不必要用框架地方保持清爽簡潔棕诵,比如如果你的頁面非常簡單裁良,沒有很多互動(dòng),就不要使用Rx年鸳、Redux趴久、Flux,甚至MVP也不需要搔确,你就簡單地在一個(gè)Activity里實(shí)現(xiàn)就好彼棍。

總的來說,合適的就是最好的膳算,不要過度設(shè)計(jì)座硕,保留在必要時(shí)重構(gòu)代碼的能力就好。畢竟涕蜂,對(duì)于軟件工程來說华匾,完備周全的設(shè)計(jì)往往起不到應(yīng)有的作用,反而是快速交付机隙,快速迭代的策略越來越被證明是一種低風(fēng)險(xiǎn)的模式蜘拉,不過,這個(gè)話題就是另外一個(gè)范疇了有鹿。

參考資料

Google開源項(xiàng)目Android Architecture Blueprints

Facebook的移動(dòng)架構(gòu)Android Flux

給 Android 開發(fā)者的 RxJava 詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旭旭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子葱跋,更是在濱河造成了極大的恐慌持寄,老刑警劉巖源梭,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異稍味,居然都是意外死亡废麻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門模庐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烛愧,“玉大人,你說我怎么就攤上這事赖欣⌒汲梗” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵顶吮,是天一觀的道長社牲。 經(jīng)常有香客問我,道長悴了,這世上最難降的妖魔是什么搏恤? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮湃交,結(jié)果婚禮上熟空,老公的妹妹穿的比我還像新娘。我一直安慰自己搞莺,他們只是感情好息罗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著才沧,像睡著了一般迈喉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上温圆,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天挨摸,我揣著相機(jī)與錄音,去河邊找鬼岁歉。 笑死得运,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锅移。 我是一名探鬼主播熔掺,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼非剃!你這毒婦竟也來了瞬女?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤努潘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疯坤,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡报慕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了压怠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眠冈。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖菌瘫,靈堂內(nèi)的尸體忽然破棺而出蜗顽,到底是詐尸還是另有隱情,我是刑警寧澤雨让,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布雇盖,位于F島的核電站,受9級(jí)特大地震影響栖忠,放射性物質(zhì)發(fā)生泄漏崔挖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一庵寞、第九天 我趴在偏房一處隱蔽的房頂上張望狸相。 院中可真熱鬧,春花似錦捐川、人聲如沸脓鹃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘸右。三九已至,卻和暖如春渐白,著一層夾襖步出監(jiān)牢的瞬間尊浓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工纯衍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栋齿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓襟诸,卻偏偏與公主長得像瓦堵,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子歌亲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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