架構就像是一場進化史,根據不同時期的需求,演變出不同的架構,車輪滾滾,到今天,移動端框架百花齊放,讓人目不暇接。但是其中的本質是磨滅不了的,換言之根本沒有磨滅而是隱藏到了人們所看不到的地方,但是依舊發揮著不可或缺的作用。
為什么需要架構?
1、一個Activity走天下,包含各種模塊和功能
2、臃腫類太多
3、不同功能,不同層次拎不清楚,混合在一起
4、重復代碼太多,復用性為差。
5、無法協作開發,
6、耦合嚴重,bug太多
等等
當我們新進一個公司,接受別人的項目的時候,基本都會說句MMP,SHI一樣的代碼啊,啥玩意啊,搞得什么啊。
我擦,我就改了一個參數,怎么全亂套了,一個功能怎么天上地下都需要改啊。
沒有經受過痛苦的人,是不會想了解架構的,只有痛苦過的人,才會急切的了解架構,好好做人,不作孽。
進化1.0 MVC
人們剛接觸編程,相信第一個遇到的框架就是MVC,不管你經意還是不經意寫出來的Android程序他就是MVC框架,只不過是MVC框架的某一個變種(最混亂的那種)。Android系統本身就根據MVC建造的。
- XML的View層
- Activity/Fragment的Controller層
- 數據Model層。
我們編寫程序剛開始應該是這種結構
View層和Controller交織在一起。在Activity里面處理各種事件和邏輯,界面的顯示和更新都在這里,除了按功能分出去的模塊外,能在Activity里面寫的都會堆在這里面,代碼常常達到上千行,別說別人,自己再回到頭看的時候也是頭皮發發麻。
所以我們開始試著學Android系統的MVC來梳理代碼。當然每個人從眾理解的也不大一樣。
不管是單向依賴還是雙向依賴都是為了把處理的職責交給Controller,這一點是不變的,所以不管你用的是哪一種形式都是不打緊的,沒有對與錯。根據自己的需求選擇最適合的一種依賴關系。
優點:
由于MVC很好的分離了視圖層和業務層,所以它具有以下優點
- 耦合性低
- 開發速度快
- 可維護性高
- 易于理解
缺點:
- 由于MVC的設計思想是從Model出發,而沒有考慮到View端的復雜性,這樣導致的問題是Model難以符合復雜多變的View端變化。導致Model的作用很小,而很多View層的職責也轉移到了Controller層。Controller變得臃腫不堪。耦合性也變高了。
- 測試困難
MVC使用的誤區
其實我在剛開始編程的時候,
誤區一:一度認為Model就是實體類(Entity)
正解:是MVC的Model應該有兩個功能:
- 處理業務邏輯
- 提供View顯示的數據
誤區二:把業務邏輯全部放在Controller端
正解:Model也會處理業務邏輯
這兩個誤區其實也和MVC的構成有關系,很容易讓人誤解,但是本質上還是不理解MVC,特別是對Model的作用不明白。
其實Model在MVC框架里面的作用不僅僅是Entry,Model在MVC中起著很重要的作用,它更應該是業務邏輯的真正實現層,而Controller層更應該作為一個橋接的作用,把View的求情轉發給Model,再把Model處理結束的消息告訴View。這樣做也就是界面和代碼(邏輯)分離。
進化2.0 MVP
但是踏入誤區的人太多了,大家都在Activity里面處理邏輯因為太方便了(寫的很爽)。
但是這樣之后,我們Activity的職責太多了,耦合也嚴重,所以我們就想著怎么能給Activity減負,同時把耦合也降下來,所以就想找個哥們來替Activity分擔的責任,大家最后都只有一個責任,各層關系也相對好理解,大家照著這個方式寫,那多好,不用加班,天天都很快樂。
既然Activty這么愿意和View搞到一起(解耦太高了),那么就讓他們倆在一起(在一起,在一起,在一起),共同負責View,我們在招聘一個職業經理人(Presenter)來處理事務,有啥事都找Presenter,你看著多方便啊,MVP是一個真正意義上的隔離View的細節和復雜性的模式
至于虛線的部分,這個和樓上的MVC的虛線一樣,每個人的理解不同,情況不同,選擇合適的就好,不用糾結誰對對錯,本質不變就可以的。
這樣就簡單多了,Activity和View兩人各種膩歪秀恩愛,各層的關系也一目了然,大家各干各的事情,想要什么和Presenter說一聲,有啥事情Presenter也會匯報,簡直爽的不要不要的。Presenter也會處理和View層的交互,Presenter在手天下我有。
優點:
1、模型與視圖完全分離(就像牛郎和和織女隔了一個銀河,每次都需要靠燕子來傳信,好可憐~~)
2、可以更高效地使用模型,因為所有的交互都發生在一個地方——Presenter內部
3、(Presener的復用)一個Presener可以用于多個視圖(View),而不需要改變Presenter的邏輯。視圖(View)的變化比模型(Model)的變化更頻繁的多 ,所以這樣超級方便。
4、(View的復用)View可以進行組件化。在MVP當中,View不依賴Model。這樣就可以讓View從特定的業務場景中脫離出來,可以說View可以做到對業務邏輯完全無知。它只需要提供一系列接口提供給上層操作。這樣就可以做高度可復用的View組件。
5、更容易單元測試
缺點:
1、由于對視圖的渲染放在了Presenter中,所以視圖View和Presenter的交互會過于頻繁。特別是需要修改視圖的時候,Presenter也需要跟著修改,很麻煩。
2、Presenter中除了業務邏輯以外,還有大量的View->Model,Model->View的手動同步邏輯,造成Presenter比較笨重,維護起來會比較困難。
3、其實總的來說就是結構很清晰,業務邏輯也很明白,耦合低,但是就是自己寫的麻煩,Presenter不好維護,工作量太大,太笨重,有點像MVC中的Activity了,職責太多了。也可以把這三個缺點總結成一句話,麻煩,尾大不掉。
進化3.0 MVVM
但是吧,你們爽了Presenter可就累壞了,大事小事都要經過Presenter,就連放個屁也要Presenter來扒褲子,日子過得久了,Presenter總會有意見啊,不帶這么使喚人的。
我們就想啊,以前過多的依賴Activity造成結構混亂,耦合太高,后來有了Presenter,雖然耦合大大降低,但是還是過于依賴Presenter,為啥總會過于依賴某一個東西呢,就不能大家都干點活,耦合性也不高的嗎?就不能大家有事相互通知嗎?非要那么懶依賴別人嗎?總要有點正能量吧。那么我們就把Presenter辭退,引入了一個新的小伙伴VM(ViewModel即 Model of View)它即包含了Modle也有View的狀態。
MVVM模式中,一個ViewModel和一個View匹配,它沒有MVP中的IView接口,而是完全的和View綁定,所有View中的修改變化,都會自動更新到ViewModel中,同時ViewModel的任何變化也會自動同步到View上顯示。
這種自動同步的原因其實就是是ViewModel中的屬性都實現了observable這樣的接口,也就是說當使用屬性的set的方法,都會同時觸發屬性修改的事件,使綁定的UI自動刷新。
在android中DataBinding幫助我們實現MVVM,在XML進行數據綁定,增加了XML的重量,不再像以前那樣僅僅是布局,均衡了各部分的職責。
所以MVVM比MVP更升級一步,在MVP中,V是接口IView, 解決對于界面UI的耦合; 而MVVM干脆直接使用ViewModel和UI無縫結合, ViewModel直接就能代表UI.
優點:
1、解決了MVP大量的手動View和Model同步的問題,提供雙向綁定機制。提高了代碼的可維護性。大大方便了開發者。(只有試過才知道有多方便)
2、簡化測試。
3、響應式編程更方便。
缺點:
1、過于簡單的圖形界面顯得大材小用(讓開發者麻煩的都是缺點)
2、視圖狀態較多,ViewModel的構建和維護的成本都會比較高。
3、數據綁定的聲明是指令式地寫在View的模版當中的,這些內容是沒辦法去打斷點debug的。(這是很碉堡的,只能自己細心了)
進化4.0 CLEAN
進化了一代有一點,作為東家的谷歌坐不住了,給不給我面子了,來來來,我給你們一個終結的,CLean~~~
WTF?這個洋蔥一個的家伙是誰?再給你一個圈就是五環了~~四個圈圈了不起???
官方的話說來就是:
獨立
- 獨立于框架。該體系結構不依賴于某些特征庫軟件庫的存在。這允許您將此類框架用作工具,而不必將您的系統塞入其有限的約束中。
- 可測試。可以在沒有UI,數據庫,Web服務器或任何其他外部元素的情況下測試業務規則。
- 獨立于UI。UI可以輕松更改,而無需更改系統的其余部分。例如,可以使用控制臺UI替換Web UI,而無需更改業務規則。
- 獨立于數據庫。您可以換掉Oracle或SQL Server,用于Mongo,BigTable,CouchDB或其他東西。您的業??務規則未綁定到數據庫。
- 獨立于任何外部機構。事實上,您的業務規則根本不了解外部世界。
依賴規則
同心圓代表軟件的不同領域。一般來說,你走的越遠,軟件就越高。外圈是機制。內圈是政策。
使這種架構工作的首要規則是依賴規則。此規則表明源代碼依賴項只能指向內部。內圈中沒有任何東西可以對外圈中的某些東西一無所知。特別是,內圈中的代碼不得提及在外圈中聲明的內容的名稱。這包括功能,類。變量或任何其他命名的軟件實體。
外圈中使用的數據格式不應該被內圈使用,特別是如果這些格式是由外圈中的框架生成的話。我們不希望外圈中的任何東西影響內圈。
官方的話就是繞,其實就是依賴是能向里依賴,白話就是內圈向外圈提供服務,比如你去食堂吃飯,選擇不同的窗口,對著里面喊到給我來一份魚香肉絲。你不用管里面的師傅是不是昨天那一個,也不用管里面的菜是不是昨天的那個口味,你只管你的目的是來一份魚香肉絲就可以了,里面的菜和師傅,也不用管你是誰,是不是個漂亮的MM,他們只管自己事情,對他們圈外的不依賴,反正你依賴我就可以了。
Clean將核心業務(Domain層)、UI相關(Presenter層)以及數據加載(Data層)彼此獨立開來,不同的層之間由接口依次連接起來,但卻又彼此不了解彼此的具體實現。
優點:
1、代碼復用性更高
2、更易于測試
3、耦合度更小
缺點:
1、學習難度大(容易懵逼)
2、代碼量大(一個小Demo都夠你寫一壺了)
從MVC->MVP->MVVM->MVP-Clean 后者解決了前者遺留的問題,把前者的缺點優化成了優點。一代更比一代強,但是都是需要代價的,學習成本更高,更加規范,但是并不一定就誰比誰更好,只有誰更適合你的項目,都有優劣,怎么選擇需要靠自己了。
其實MVX系列的本質一直未變:
- 關注點分離原則
- 高內聚低耦合原則
同時也希望適度設計,不要太過追求某一點。會得不償失。找到最經濟的方案才是王道,也可以多種方案配合一起配合。
如何能夠更好的將多種架構表現在一款App里面呢?對!組件化。
組件化
組件化開發就是將一個app分成多個模塊,每個模塊都是一個組件(Module),開發的過程中我們可以讓這些組件相互依賴或者單獨調試部分組件等,但是最終發布的時候是將這些組件合并統一成一個apk,這就是組件化開發。
不同的Module我們根據職責劃分選擇不同的架構,可以最經濟的開發一款APP。
目前成熟的方案有阿里的ARouter,通過路由的方式進行通信,感興趣的同學可以學習下。
- 優點
1、低耦合
2、可以針對測試(降低測試成本)
3、復用性強
4、支持并行開發
5、適合使用多進程
6、減小編譯時間
- 缺點
1、不適合小型應用或者獨立開發
2、各組件開發人員聯調,開發進度不一致等問題
- 應用場景
假如一個app用戶量很大,業務豐富,比如某寶,很明顯不是一個小團隊可以開發的了的,如果不分模塊的話,工程的復雜度就太大了,編譯時間估計半天都完不成,維護更不用說了,簡直不是人干的了。所以很適合分模塊來開發。各個模塊的耦合性也能降到最低,不至于一個模塊有問題,牽連別的模塊。編譯時間也會大大減小。每個模塊相當于一個小APP,更容易靈活的編譯,編寫。測試也只需要測試本模塊,最后聯調整體就可以了。所以說業務越復雜,組件化越有優勢。
小結
移動端架構的差異化體現在通信機制上。通信機制主要分為3種:
1) 對象持有
2) 接口持有
3) 路由
對象持有最簡單,但是解耦率最低;
接口持有較為復雜,實現解耦的需求,但是解耦不徹底,相互持有交互方的接口。
路由機制可以實現完全解耦,實現組件化
完了嗎?不不不~~移動端不僅僅Android和IOS,還有前端,上面僅僅是MVX的進化史,同時還有不同分支的進化。
當下移動端的趨勢,越來越向大前端靠攏了,Android的道友們也越來越瑟瑟發抖,看到RN,FLutter等等的興起,越來越覺得僅僅學習Android是不夠的,還要學習跨平臺,大前端的知識。
俗話說他山之石可以攻玉,我們對架構的思考也是如此,不能僅限于自己的一畝三分地,也要學習下友軍的套路。
這類一般都是響應式視圖的系統,MVVM就是個響應式,所以其實都是有聯系的。
進化 5.0 Flutter/ReatNative
- Flutter
- 是google用以幫助開發者在Ios和Android兩個平臺開發高質量原生應用的全新移動UI框架,也是據說要把Android替換掉的一個恐怖存在(目前現在還是個弱雞)
- React Native
- 讓開發者使用 JAVAScript 和 React 編寫應用,利用相同的核心代碼就可以創建 Web,iOS 和 Android 平臺的原生應用。React Native 的宗旨是,學習一次,高效編寫跨平臺原生應用。
- ReatNative
JS 開發者可以用類似DOM編程模型就可以開發原生APP,畫UI只需要畫到virtual DOM 中,不需要特別關心具體的平臺, RN 會把應用的JS代碼編譯成一個js文件,RN的整體框架目標就是為了解釋運行這個js 腳本文件,通過bridge 傳遞到native , 然后根據數據屬性設置各個對應的真實native的View。
RN官方給的框架是Flux
- action 封裝請求
- dispatcher 注冊處理器、分發請求
- store 是處理器,處理業務邏輯,保存數據
- view 根據store提供的數據進行展現;接受用戶的輸入并發出action請求。
解耦很細,做一個功能會涉及很多地方,所以人們對于這個官方架構進行簡化
Reflux:
這個三層框架就大大簡化了flux的復雜交互。
不管是面向對象還是面向狀態,其實本質上是一致的。三層框架能夠很好處理視圖,數據,事件,邏輯的問題。
我們也可以參考另外一種架構
Redux:
我們可以看出 其實也是分為三層,組件,Store,Action。組件綁定這Action和state,store reducer都是頁面單例,易于管理。action為請求dto對象,是請求類型,請求數據的載體,reducer是處理請求的方法。不允許有狀態,必須是純方法。必須嚴格遵守輸入輸出,中間不允許有異步調用。不允許對state直接進行修改,要想修改必須返回新對象。
這就是 面向狀態編程
react的組件只關注數據的最終狀態,數據是怎么產生的并不關心。這個是RN的核心思想。
- 優點
1、提升產品迭代速度,APP迭代周期變短
2、減少研發成本(可不,ios和android都可以下崗了)
3、提升開發測試效率(不用雙端兩套代碼分開測試了)
- 缺點
1、原生有些功能實現不了或者說很復雜
2、需要掌握IOS和Android的知識,個人學習成本高
3、需要兼容IOS和Android(很苦逼)
Flutter
今年谷歌推出了Flutter的Beta版本,離正式的出生越來越近了。我們來看看這個新同學吧。
Flutter主要解決了移動開發中的兩個重要問題,一是原生應用程序的性能與平臺的集成;二是提供多平臺、可移植的UI工具包支持高效應用開發。
和RN的跨平臺思想不同
RN是將一種設計理念延伸到兩個平臺,而Flutter則實現了一套代碼,部署多個平臺。解決了RN開發需要IOS和Android基礎的窘迫和成本。
在Flutter中,每個應用程序都是Widget,這點和其他的應用框架不一樣,Flutter的對象模型是統一的,也就是控件。
Flutter 基本上就是一個 V(View),響應式視圖,它可以是無狀態或有狀態的 widget,就連 AppCompatActivity 也是一個 widget。是不是很過分?簡單到粗暴。采用widget 和 state分離 ,比如我們在原生里大量重復代碼來管理 Activity 的生命周期。但是在 Flutter 中,這是不需要的,從設計的角度就解決了這個問題。就像LifeCycles也是這種思想,解決了生命周期的問題。
對于這種面向狀態編程的思想,架構和RN是類似,同時我們也期待Google的官方架構指導的出現,會不會有更多的驚喜呢?
- 優點
1、響應式視圖,不需要JavaScript的橋接器
2、性能更好,兼容性更好
3、代碼將AOT編譯為本機(ARM)代碼
4、美觀,可定制的UI組件,開發人員完全控制UI組件和布局
5、熱重新加載
- 缺點
1、包體很大需要打包自己的SDK
2、占用內存空間大
3、啟動時間很慢
4、流暢性和原生有差距
不過因為FLutter還沒與正式出版,相信FLutter會解決這些缺點的。
- RN和Flutter差別:
對于這兩者系統架構的區別 這里有兩張圖:
我們可以看出來 主要差別就是Widgets的差別,還有Bridge中間層的區別,Flutter從理論上的速度要別RN高很多,沒有了中間層的倒轉,有自己的Widgets可以保證IOS和android上的統一。
實現跨平臺的這兩種方式也是架構設計的體現,Bridge有沒有和Presenter很相似,連接著js和系統。
RN是將一種設計理念延伸到兩個平臺,而Flutter則實現了一套代碼,部署多個平臺。
不同的設計思想,會走向不同的路,到底是哪一種走的更好,這個可能就需要隨著時間去檢驗了,雖然理論上FLutter要比RN好很多,但是現在的顯示很殘酷。不過FLutter才是Beta版本,潛力非常大。
寫在最后
本文把目前移動端主流的架構順了一遍,也是我自己對架構認識的一個時間軸,從剛開始的胡亂編寫,到后來有些章法,不過還是對框架的領悟很淺,肯定有很多謬論錯輪,希望以我個人對架構的思考可以拋磚引玉,如果可以給你一些幫助,那是極好的一件事情了。
不管是RN還是Flutter,亦或是原生的IOS和Android,其實他們本質編程思想是一致,同樣,隨著更多更方便的框架出來,我們的理解能力和學習能力受到了很大的挑戰,很多同學都說學不動,但是事實上技術的更新換代遠比我們學習新知識要快,往往我們剛學會這個,又會出了另外一個,我們只要掌握了它的核心思想,就不會那么累和無奈了。
這就是技和道的差別,通過技最終掌握道,而不是以技學技,那樣沒有終點。
我們在實際中如何選擇架構,其實這個的因素很多,最關鍵的是一個經濟,比如項目時間比較短,還是獨立開發,我們可能就要用MVC了,或者說應用的功能相對簡單,也會取用MVC,至于MVP,或者MVVM,CLEAN,這個對于大型開發,特別是協作開發,有著很大的幫助。因為我們工作不僅僅是技術,還有項目周期,老板的喜好,歷史遺留問題,所以選擇最經濟的一個,而不是選擇那個公認最好的那個。
移動端的趨勢越來越走向統一了,我們發現越來越多的公司,需要大前端的人才,所以要一直學習,創造時代的人都沒有說累,我們跟著學習的人更不應該喊累,沒有學不動,只有不想學。同時歡迎大家來剛哥的知識星球,一起激勵,一起砥礪前行。
好了,文章到這里就結束了如果你覺得文章還算有用的話,不妨把它們推薦給你的朋友。
以前我們一直被公司和技術牽著走,并不是自己在選擇技術,而是不自覺地被推到了現在尷尬的處境。想想有多少人對于自己將來要發展的方向和技術類型進行過深入思考和比較呢?
對于程序員來說,要學習的知識內容、技術有太多太多,要想不被環境淘汰就只有不斷提升自己,從來都是我們去適應環境,而不是環境來適應我們!
而當你有了學習線路,學習哪些內容,也知道以后的路怎么走了,理論看多了總要實踐的,我在這里給你們整理了我自己的Android 學習,面試文檔,視頻收集大整理,有興趣的伙伴們可以看看~
【私信】回復【安卓資料】即可獲取:
Android 學習,面試文檔,視頻收集大整理