Android 應(yīng)用架構(gòu)概述

通常一個App的成長過程都是這樣的:

第一階:先用最少的成本和時間快速把東西做出來。

第二階段:積累一定用戶量之后再小步快跑的迭代功能。

第三階段:性能和體驗上逐步求精。

我發(fā)現(xiàn)好多項目在第二階段和第三階段耗費了好多本來不應(yīng)該浪費的人力成本、時間成本。究其原因就是因為前期忽略了合理的架構(gòu),我甚至經(jīng)歷過因為前期的設(shè)計不合理導(dǎo)致后期技術(shù)債務(wù)太多項目瀕臨死掉、整個項目組全員換掉重造鍋爐的境地。所以,我們?yōu)槭裁床患饶苁褂米詈啙嵉姆绞綄崿F(xiàn)功又能要保證后期靈活的擴(kuò)展能力呢?下面是本人最近項目實踐的一些整理,拋磚引玉,希望一起討論。文章首發(fā):http://www.liuguangli.win/archives/299。

視圖和數(shù)據(jù)

好的代碼一定是層次分明、職責(zé)分明,糟糕的代碼架構(gòu)就是沒有層次沒有模塊,每次修改代碼都是牽一發(fā)動全身。從大的方面來講Android應(yīng)用都會被分為兩層:視圖層、數(shù)據(jù)層。

數(shù)據(jù)和視圖

視圖:一般以Activity為依托的各種View,包含View、ViewGroup和WebView,還有各種fragment。

數(shù)據(jù):支撐整個應(yīng)用邏輯的數(shù)據(jù),分為兩類。一類存儲在遠(yuǎn)端服務(wù)器上的,一類在本地。遠(yuǎn)端數(shù)據(jù)需要通過網(wǎng)絡(luò)(通常是Http)獲取,本地數(shù)據(jù)包括sqlite存儲的關(guān)系型數(shù)據(jù),文件系統(tǒng),內(nèi)存緩存對象。

必然聯(lián)系

用數(shù)據(jù)驅(qū)動視圖變化,這才產(chǎn)生了豐富多彩的應(yīng)用交互世界,所以,視圖和數(shù)據(jù)的聯(lián)系是必然的。

視圖數(shù)據(jù)的直接聯(lián)系

在Android平臺和整個移動開發(fā)生態(tài)都發(fā)展的非??欤贏ndroid興起之初,對層的重要性不是太強(qiáng)調(diào),所有很多開始寫Android程序的開發(fā)對層劃分不是太清晰 ,看到很多入門書本里很多直接在Activity里面直接處理數(shù)據(jù)的代碼,例如直接在Activity里面直接調(diào)SharedPrefrence操作數(shù)據(jù),直接在Activity 里面直接調(diào)用網(wǎng)絡(luò)請求等,很多初級選手的很容易寫出這樣沒有層次的代碼出來。當(dāng)接口變更,當(dāng)存儲方式更好的時候整個UI層面的邏輯都受影響。

解耦

好一點的設(shè)計必然會做一次隔離:盡量做到UI和數(shù)據(jù)彼此透明、“互不干涉內(nèi)政”。

解耦

隔離的好處是:一、 提高可維護(hù)性。在UI邏輯發(fā)生變化甚至整個端掉都不會影響到處理邏輯。二、 提高可復(fù)用性。復(fù)用通常只數(shù)據(jù)的復(fù)用,數(shù)據(jù)邏輯不受UI的左右,由此可以服務(wù)于多個UI視圖。三、 可讀性。層次分清之后按照統(tǒng)一的架構(gòu)思路去理解代碼,當(dāng)然還得靠開發(fā)人員良好的編程素養(yǎng)和代碼規(guī)范。

那么怎么做到隔離呢?關(guān)于解耦,業(yè)內(nèi)比統(tǒng)一的可以歸納為兩種:MVC、MVP(MVVM)。

MVC解耦

mvc

V:在MVC架構(gòu)中Activity(托管Fragment,View,WebView等)首先充當(dāng)V的角色。

M:業(yè)務(wù)邏輯層劃分出來專門處理數(shù)據(jù)。例如:數(shù)據(jù)的http請求,數(shù)據(jù)解析和儲存等邏輯都封裝在這一層。Activity不直接和Http,Dao(數(shù)據(jù)訪問對象層)直接有聯(lián)系了,視圖數(shù)據(jù)從此為路人。

C:C是什么?MVC這個模式及概念,在移動應(yīng)用開發(fā)出新之前就已經(jīng)產(chǎn)生了,最經(jīng)典的水用場景JSP +servlet+javabean,我開始接觸MVC也是在做JavaWeb開發(fā)的時候。后來Android開發(fā)火了,把這套模式搬上來。但是C套上了不太好理解。Android應(yīng)用開發(fā)中,套上MVC,Activity 兼具V和C的角色。

MVP解耦

很多時候視圖層面還是充斥中很多復(fù)雜的邏輯,例如UI事件的響應(yīng)處理,網(wǎng)絡(luò)響應(yīng)的回調(diào)等等,充斥著各種監(jiān)聽器的回調(diào)。我們期望視圖V便當(dāng)更簡單、更純粹,V只負(fù)責(zé)繪制和刷新其他邏輯都不用管了,也不想和M有直接的聯(lián)系。從MVC的VC(Activity)中我們分離一層出來叫做Presenter,由它來負(fù)責(zé)調(diào)度UI何時刷新、由它來接受UI的事件響應(yīng)并傳達(dá)指令給M。從此V和M是路人,V和數(shù)據(jù)的距離跟遠(yuǎn)了。

mvp

V:Activity為代表,這時候的Activity更為簡單了,只負(fù)責(zé)UI的繪制和刷新。

P:負(fù)責(zé)傳達(dá)指令。向上接收V的事件指令并需要的時候傳達(dá)給M,向下接收M的指令并通知V刷新UI。

M:只負(fù)責(zé)出來數(shù)據(jù)邏輯。其實還可以細(xì)分一些東西,比如Http請求,很多時候我們的Http框架都是用的第三方開源框架,如果有一天更優(yōu)秀的框架出現(xiàn)了,要更換,怎么才能做到不影響其他層次?如果我門做了分層隔離那么,我門可以很輕松的換掉,如果沒有做分層隔離,那么我門可能要在每一個功能模塊的M中修改代碼,修改代價是巨大的,所以一遍第三方開源框架我都不會直接使用而是在業(yè)務(wù)上做一層抽象隔離。同理,本地數(shù)據(jù)的存儲,也有必要做響應(yīng)的封裝或隔離,因為今天是用Litepal,也許某一天想用GreenDao了,只需要修改封裝類的代碼就好了。

MVP的依賴關(guān)系:

MVP依賴關(guān)系

MVP類圖:

MVP類圖

我們把每一層都抽象成一個接口,例如V層,我們定義一個接口為View(不要和Android API里的View弄混了),讓后Activity成為這個View的具體實現(xiàn)。每一層對另一層的依賴都是接口依賴,并不關(guān)心另一層的具體實現(xiàn),每一層我們都可以寫不同的實現(xiàn),隨時切換,這就意味著,有一天如果有一層不好用了,我們可以輕松的重寫另一個實現(xiàn)來替換掉,而不是如履薄冰的修改。

MVP demo

https://github.com/liuguangli/androidmvp

下篇文章將以登錄為業(yè)務(wù)場景分析MVP的具體實現(xiàn)。下篇:《Android應(yīng)用架構(gòu)之MVP實現(xiàn)》

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

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

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