倪紅軍
(南京師范大學(xué)泰州學(xué)院,江蘇泰州225300)
隨著移動(dòng)互聯(lián)網(wǎng)技術(shù)和智能終端技術(shù)的發(fā)展,基于Android平臺(tái)的智能設(shè)備在人們的生活中越來(lái)越普及,運(yùn)行于Android平臺(tái)上的相應(yīng)軟件也越來(lái)越多,每個(gè)軟件承載的功能也是越來(lái)越強(qiáng),采用傳統(tǒng)的MVC(Model—View—Controller)開發(fā)模式開發(fā) 的Android平臺(tái)軟件,視圖層(View)一般采用XML文件進(jìn)行界面描述,控制層(Controller)的功能通常由Activity擔(dān)當(dāng),模型層(Model)用來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)及業(yè)務(wù)計(jì)算等的操作。雖然MVC模式將界面呈現(xiàn)和邏輯代碼分離開了,但View對(duì)應(yīng)的XML文件實(shí)際能實(shí)現(xiàn)的功能很少,很多界面呈現(xiàn)都必須由Controller對(duì)應(yīng)的Activity完成,這樣Activity既充當(dāng)了View的角色,又充當(dāng)了Controller的角色。隨著用戶界面及其業(yè)務(wù)邏輯的復(fù)雜度不斷提升,Activity的職責(zé)也會(huì)不斷增加,使得Activity越來(lái)越龐大臃腫和耦合度越來(lái)越高,從而導(dǎo)致項(xiàng)目的后期維護(hù)變得越來(lái)越復(fù)雜[1-3],對(duì)于開發(fā)周期比較短的小型項(xiàng)目這種模式是可以接受的,但如果開發(fā)一個(gè)界面和業(yè)務(wù)邏輯復(fù)雜度都很高的項(xiàng)目來(lái)說(shuō),這種開發(fā)模式耦合度高、維護(hù)困難等問(wèn)題就突顯出來(lái)了。綜上所述,傳統(tǒng)的MVC開發(fā)模式并不很適合運(yùn)用于Android平臺(tái)軟件的開發(fā)。
針對(duì)以上問(wèn)題,在進(jìn)行Android平臺(tái)軟件開發(fā)時(shí),需要探索另外一種更適合的開發(fā)模式進(jìn)行Android平臺(tái)軟件的開發(fā),以便將復(fù)雜的業(yè)務(wù)邏輯進(jìn)行分解處理,讓Activity的職責(zé)更加單一、代碼耦合度更低、軟件結(jié)構(gòu)層次更加清晰,以提高代碼的靈活性和可維護(hù)性。經(jīng)過(guò)研究和實(shí)踐發(fā)現(xiàn)MVP模式能夠很好的解決這類問(wèn)題。本文通過(guò)對(duì)MVP開發(fā)模式的研究分析,探討Android應(yīng)用開發(fā)中使用MVP開發(fā)模式的原因,并結(jié)合基于Web Service的教師任課信息管理系統(tǒng)的登錄模塊實(shí)現(xiàn)過(guò)程,探討Android應(yīng)用開發(fā)中使用MVP開發(fā)模式的軟件設(shè)計(jì)流程。
MVP(Model-View-Presenter)模式是 2000年左右由IBM開發(fā)出來(lái)的一個(gè)針對(duì)C++和Java的編程模型,是 MVC(Model-View-Controller)模式演變而來(lái)的,在應(yīng)用開發(fā)中它們具有基本相通的設(shè)計(jì)思想:Controller/Presenter負(fù)責(zé)邏輯的處理,Model提供數(shù)據(jù),View負(fù)責(zé)顯示。MVC的設(shè)計(jì)模型圖如圖1所示,MVP的設(shè)計(jì)模型圖如圖2所示。
圖1 MVC設(shè)計(jì)模式
圖2 MVP設(shè)計(jì)模式
在MVC設(shè)計(jì)模式中,Model是應(yīng)用程序中用于處理業(yè)務(wù)邏輯的部分,通常負(fù)責(zé)定義數(shù)據(jù)修改和操作的業(yè)務(wù)規(guī)則;View是應(yīng)用程序處理數(shù)據(jù)顯示的部分,通常負(fù)責(zé)展示依據(jù)Model創(chuàng)建的數(shù)據(jù);Controller是應(yīng)用程序中處理用戶交互的部分,通常負(fù)責(zé)處理流入的請(qǐng)求[4-6]。當(dāng)View接收用戶的輸入后,可以通過(guò)Controller修改對(duì)應(yīng)的Model實(shí)例數(shù)據(jù),也可以由View層直接更新Model數(shù)據(jù)[7-10];當(dāng)Model的數(shù)據(jù)發(fā)生變化并需要修改用戶界面時(shí),可以通過(guò)Controller實(shí)現(xiàn)。
從圖1可以看出,在MVC模式中View是可以直接訪問(wèn)Model的,所以View中也會(huì)包含Model信息和一些業(yè)務(wù)邏輯。Model不依賴于View,但View是依賴于Model的。由于一些業(yè)務(wù)邏輯在View里實(shí)現(xiàn),從而導(dǎo)致View的更改比較困難,業(yè)務(wù)邏輯也無(wú)法重用。
在MVP設(shè)計(jì)模式中,Model和View的主要功能與MVC設(shè)計(jì)模式基本相同,Presenter是Model與View之間的橋梁,它從Model獲得數(shù)據(jù)后,返回給View,使得View與Model之間沒(méi)有耦合,也將業(yè)務(wù)邏輯從View中抽離出來(lái)。
從圖2可以看出,在MVP模式中Presenter完全把Model和View進(jìn)行了分離,主要的程序邏輯在Presenter里實(shí)現(xiàn)。而且,Presenter與具體的View是沒(méi)有直接關(guān)聯(lián)的,而是通過(guò)定義好的接口進(jìn)行交互,從而使得在變更View時(shí)可以保持Presenter不變。這樣的分層模式大大降低了Model層與View層的耦合度,一方面可以實(shí)現(xiàn)View層和Model層的單獨(dú)開發(fā)與測(cè)試,互不依賴;另一方面有利于Model層的封裝復(fù)用,大大減少了代碼量[11-12]。
在Android應(yīng)用開發(fā)中使用MVP模式,將Model層和View層通過(guò)Presenter層實(shí)現(xiàn)完全分分離,主要的業(yè)務(wù)邏輯在Presenter層中實(shí)現(xiàn)。Presenter層持有View層和Model層的Interface(接口)引用,View層持有Presenter層的Interface(接口)引用。當(dāng)View層的某個(gè)用戶界面(UI)需要展示數(shù)據(jù)時(shí),首先調(diào)用Presenter層的相關(guān)Interface,然后Prensenter層調(diào)用Model層請(qǐng)求數(shù)據(jù),當(dāng)Model層數(shù)據(jù)加載成功后,調(diào)用Presenter層的CallBack(回調(diào)方法)通知Presenter層數(shù)據(jù)加載完畢,最后Presenter層調(diào)用View層的Interface將加載后的數(shù)據(jù)在用戶界面展示。
使用MVP模式進(jìn)行Android應(yīng)用開發(fā)時(shí),MVP模式主要包含4個(gè)關(guān)鍵部分:
1)View:由 Activity類或 Fragment類實(shí)現(xiàn),負(fù)責(zé)與用戶的交互及視圖部分展示;
2)View interface:需要View實(shí)現(xiàn)的接口,其中定義了View行為的抽象,View通過(guò)該接口與Presenter進(jìn)行交互,使用該接口主要為降低程序間的耦合度;
3)Model:負(fù)責(zé)存儲(chǔ)、訪問(wèn)數(shù)據(jù)的實(shí)體類,數(shù)據(jù)可以是遠(yuǎn)端的Server API、本地?cái)?shù)據(jù)庫(kù)或SharedPrefer?ences等;
4)Presenter:負(fù)責(zé)完成View與Model間交互的業(yè)務(wù)邏輯類,一個(gè)Presenter可以對(duì)應(yīng)多個(gè)View。
下面就以基于Web Service的教師任課信息管理系統(tǒng)的登錄模塊為例介紹MVP模式在Android應(yīng)用開發(fā)中的實(shí)現(xiàn)過(guò)程。登錄模塊包括Web Service服務(wù)器端和Android客戶端兩個(gè)部分。
服務(wù)器端是基于ASP.Net平臺(tái)創(chuàng)建的Web Service,向開發(fā)者提供調(diào)用接口如圖3所示。其中username表示登錄用戶的用戶名,password表示登錄用戶的密碼。如果登錄用戶是管理員,返回“1”;如果登錄用戶是普通教師,返回“2”;否則返回“3”。Web Service的實(shí)現(xiàn)技術(shù)不是本文研究?jī)?nèi)容,所以不作詳述。
圖3 Web Service調(diào)用接口
圖4 客戶端目錄結(jié)構(gòu)
客戶端使用MVP模式實(shí)現(xiàn),實(shí)現(xiàn)的目錄結(jié)構(gòu)如圖4所示。
登錄模塊的Model層主要負(fù)責(zé)從Web Service服務(wù)器獲取登錄信息,由ITeacher和LoginOnListener兩個(gè)接口類及一個(gè)TeacherImpl實(shí)現(xiàn)類組成。
1)ITeacher和LoginOnListener接口類
ITeacher接口定義了需要實(shí)現(xiàn)的login方法,其關(guān)鍵代碼如下:
LoginOnListener接口定義了登錄后需要處理的adminSuccess()、teacherSuccess()和loginFailed()方法,分別表示管理登錄成功、老師登錄成功和登錄失敗。
2)TeacherImpl實(shí)現(xiàn)類
由于從Web Service服務(wù)器獲取登錄信息是一個(gè)耗時(shí)操作,所以需要使用線程實(shí)現(xiàn)[13-17]。其中LinkWeb是自定義的一個(gè)訪問(wèn)Web Service的工具類,關(guān)鍵代碼如下:
View層登錄模塊展示的組件是AppCompatAc?tivity,其布局文件使用嵌套的RelativeLayout布局,運(yùn)行后的效果如圖5所示。為了方便Presenter與View的交互,View層定義了一個(gè)ITeacherLoginView接口類,該接口中包含了登錄成功頁(yè)面跳轉(zhuǎn)方法、加載過(guò)程中給用戶信息提示方法、從登錄界面獲取用戶名和密碼的方法,其關(guān)鍵代碼如下:
圖5 登錄界面
在登錄界面AppCompatActivity中實(shí)現(xiàn)ITeacher?LoginView 接口,并重寫 toFirstActivity()、showToast(String msg)、getUsername()及 getPassword()方法,以實(shí)現(xiàn)相關(guān)功能。
View層需要調(diào)用Presenter層訪問(wèn)Model層的信息,所以在Presenter層定義了一個(gè)實(shí)現(xiàn)LoginOnLis?tener接口的LoginPresenter類,其中包含一個(gè)需要傳入View層的接口對(duì)象iTeacherLoginView、一個(gè)用于訪問(wèn)Model層的信息的login方法及LoginOnListener接口中需要重寫的方法,其關(guān)鍵代碼如下:
當(dāng)用戶在LoginActivity界面單擊Button后,Logi?nActivity會(huì)調(diào)用 LoginPresenter的 login方法,Login?Presenter的login方法中又會(huì)調(diào)用ITeacher中的login方法。ITeacher中的login方法是加載數(shù)據(jù)的核心,通過(guò)自定義的LinkWeb工具類中的connectService?ForLogin方法請(qǐng)求Web Service服務(wù)器接口獲取數(shù)據(jù),并通過(guò)LoginOnListener接口回調(diào)給LoginPresenter。
文中通過(guò)對(duì)Android應(yīng)用開發(fā)中使用MVC模式實(shí)現(xiàn)過(guò)程進(jìn)行分析,發(fā)現(xiàn)了MVC模式中充當(dāng)View層功能的xml文件控制能力較弱,諸如動(dòng)態(tài)隱藏/顯示按鈕等功能在xml中根本沒(méi)有辦法實(shí)現(xiàn),只能將實(shí)現(xiàn)代碼寫到Activity中,造成了Activity在MVC模式中既充當(dāng)了Controller,又充當(dāng)了View,從而導(dǎo)致Activity臃腫不堪、業(yè)務(wù)邏輯耦合度高及項(xiàng)目后期維護(hù)難度大等問(wèn)題。
根據(jù)MVP模式的設(shè)計(jì)思想,Android應(yīng)用開發(fā)中的Model與MVC模式中一樣,而Activity不再是Controller的角色,而純粹是View的角色,所有的業(yè)務(wù)事件統(tǒng)一由Presenter負(fù)責(zé)處理,Model和View完全解耦,從而使Android平臺(tái)的應(yīng)用開發(fā)模塊職責(zé)劃分明顯、代碼復(fù)用度高和靈活性強(qiáng),便于項(xiàng)目的后期維護(hù)和功能擴(kuò)展。為了驗(yàn)證MVP模式在Android應(yīng)用開發(fā)中的可行性,最后基于MVP模式設(shè)計(jì)并實(shí)現(xiàn)了教師任課信息管理系統(tǒng)登錄模塊,達(dá)到了預(yù)期效果。