潘鳳 江蘇聯(lián)合職業(yè)技術(shù)學(xué)院淮安生物工程分院
從功能手機(jī)到智能手機(jī),從3G到4G再到如今的5G,手機(jī)中的APP越來越豐富,提供的功能越來越強(qiáng)大,涉及的領(lǐng)域越來越廣。在這背后,離不開移動(dòng)生態(tài)和APP開發(fā)技術(shù)的不斷發(fā)展。在移動(dòng)端操作系統(tǒng)市場(chǎng)中,Android操作系統(tǒng)占比超過了百分之七十。這幾年來,Android操作系統(tǒng)在不斷地迭代更新,同時(shí),Android應(yīng)用架構(gòu)也不斷發(fā)展。最初的一代架構(gòu)是MVC,但是Activity過于臃腫;為了解決該問題,出現(xiàn)了二代架構(gòu)MVP,新增了presenter層,作為控制中心,分擔(dān)原來Activity中的部分功能,處理View于Model間的交互和業(yè)務(wù)邏輯;如今Android主流應(yīng)用架構(gòu)是MVVM,MVVM的出現(xiàn)解決了MVP架構(gòu)中View層大量接口和實(shí)現(xiàn)類等問題,更加靈活高效。
MVVM架構(gòu)共分為三層:Model層、View層、ViewModel層。Model表示模型層,主要負(fù)責(zé)獲取視圖層所需要的數(shù)據(jù),數(shù)據(jù)源通常是網(wǎng)絡(luò)和本地?cái)?shù)據(jù)庫(kù)。View層是視圖層,主要負(fù)責(zé)界面的繪制和交互,Android項(xiàng)目的View層通常是XML和Activity;ViewModel層是視圖-模型層,主要負(fù)責(zé)業(yè)務(wù)邏輯的處理,串聯(lián)View層與Model層間,當(dāng)Model層更改時(shí),ViewModel層反饋給View層,引發(fā)頁面的刷新。Android項(xiàng)目中引入MVVM架構(gòu)可以帶來以下幾點(diǎn)優(yōu)勢(shì)。
1.各層級(jí)低耦合
MVVM架構(gòu)中,數(shù)據(jù)模塊和界面模塊是相互獨(dú)立的,通過ViewModel建立關(guān)聯(lián)。單純從數(shù)據(jù)的角度來看,Model負(fù)責(zé)提供數(shù)據(jù),ViewModel負(fù)責(zé)處理數(shù)據(jù),View負(fù)責(zé)展示數(shù)據(jù)。View層想展示什么樣的樣式,完全由自己決定。如果View層的樣式發(fā)生變化,只要數(shù)據(jù)格式不變,那么ViewModel層和Model層就不需要做任何改動(dòng)。如果Model數(shù)據(jù)源發(fā)生了變化,只要數(shù)據(jù)格式不變,那么View層也不需要做任何改動(dòng)。而在MVC或者M(jìn)VP架構(gòu)中,當(dāng)界面樣式改變時(shí),可能就需要改變獲取控件的方式,改變更新界面的接口等等。
2.雙向綁定、數(shù)據(jù)驅(qū)動(dòng)
在MVVM架構(gòu)中,可以通過數(shù)據(jù)綁定框架實(shí)現(xiàn)數(shù)據(jù)和控件的雙向綁定,當(dāng)數(shù)據(jù)改變時(shí)會(huì)自動(dòng)驅(qū)動(dòng)View層更新,View層控件改變時(shí)可以自動(dòng)反饋到數(shù)據(jù)上,這樣ViewModel層可以專注于處理數(shù)據(jù)和業(yè)務(wù)邏輯,不需要去關(guān)注View層的邏輯,比如如何獲取用戶的輸入,如何更新界面,如何獲知用戶的交互事件等等。View層和ViewModel層之間通過數(shù)據(jù)進(jìn)行串聯(lián),一方改變都會(huì)自動(dòng)影響另外一方。每一層只關(guān)注自己的事情,整個(gè)項(xiàng)目的結(jié)構(gòu)非常清晰明了。
3.團(tuán)隊(duì)協(xié)作,提高效率
在MVVM架構(gòu)下,各層級(jí)之間的耦合程度很低,所以可以根據(jù)層級(jí)對(duì)整個(gè)項(xiàng)目進(jìn)行劃分,進(jìn)而明確地分工,這樣極大地提高了個(gè)人和整個(gè)團(tuán)隊(duì)的開發(fā)效率。
4.可復(fù)用性
如果對(duì)于同一份數(shù)據(jù),需要多種樣式進(jìn)行展示,那么同一個(gè)ViewModel就可以供多個(gè)View使用。如果由于需求的變化導(dǎo)致樣式不斷變化,那么我們只需要更改對(duì)應(yīng)的View層就可以了。
5.易于測(cè)試
由于ViewModel層和View層是相互獨(dú)立的,一個(gè)專注于數(shù)據(jù)和業(yè)務(wù)邏輯的處理,一個(gè)專注于界面的繪制和交互,那么開發(fā)人員在做單元測(cè)試的時(shí)候,可以對(duì)兩個(gè)層級(jí)分別進(jìn)行測(cè)試,極大地方便了測(cè)試。
6.優(yōu)化代碼
Android中findViewById等模式化代碼無需手動(dòng)編寫,MVVM中的數(shù)據(jù)綁定框架可以直接完成該工作,極大地提高了工作效率,同時(shí)還可以提高XML布局文件的解析速度。
2015 年谷歌在Google I/O上提出了Data Binding庫(kù),目的是減少Android開發(fā)中的大量模板代碼(setText等),增加代碼及邏輯清晰度,提高開發(fā)效率和維護(hù)效率。同時(shí),這也意味著,在Android開發(fā)中支持MVVM的開發(fā)模式,Data Binding可以使得數(shù)據(jù)對(duì)象直接綁定到XML布局文件中,數(shù)據(jù)發(fā)生變化時(shí)會(huì)直接反映到View上;View狀態(tài)發(fā)生變化時(shí)也會(huì)反應(yīng)到數(shù)據(jù)上。Android項(xiàng)目中使用Data Binding搭建MVVM架構(gòu),需要以下幾個(gè)步驟:
1.利用Data Binding搭建View層。引入Data Binding框架后,XML布局文件和原始文件相比,增加了layout標(biāo)簽和data標(biāo)簽。data標(biāo)簽用來綁定數(shù)據(jù)對(duì)象,這樣布局標(biāo)簽就可以直接使用變量中的屬性。Activity中需要使用Data Binding綁定對(duì)應(yīng)的布局文件和數(shù)據(jù)對(duì)象,數(shù)據(jù)對(duì)象需要實(shí)現(xiàn)Observable接口,這樣數(shù)據(jù)對(duì)象就有了更新通知能力,一旦數(shù)據(jù)層的對(duì)象發(fā)生變化,View層就會(huì)自動(dòng)完成相應(yīng)的變化。
2.搭建ViewModel層。ViewModel層主要負(fù)責(zé)業(yè)務(wù)邏輯的處理,持有ObservableField等View層所需要的數(shù)據(jù)對(duì)象,還有Model層的對(duì)象。通過Model層對(duì)象調(diào)用接口獲取數(shù)據(jù),獲取數(shù)據(jù)成功后給ObservableField等數(shù)據(jù)對(duì)象賦值,一旦數(shù)據(jù)的值發(fā)生變化后,View層對(duì)應(yīng)的頁面就會(huì)刷新。
Data Binding搭建的MVVM架構(gòu)有很多優(yōu)點(diǎn),比如雙向綁定技術(shù)可以讓數(shù)據(jù)的一致性很好、增強(qiáng)了View層和ViewModel層聯(lián)動(dòng)性、減少了很多模式化代碼、自動(dòng)判空技術(shù)減少了低級(jí)錯(cuò)誤的發(fā)生等等。但是,Data Binding框架也有一些缺陷,首先Data Binding框架對(duì)XML布局文件的侵入性比較大,增加了學(xué)習(xí)成本,同時(shí)還影響了XML布局文件的復(fù)用性;其次,由于XML布局文件無法進(jìn)行調(diào)試,而數(shù)據(jù)綁定讓一部分邏輯轉(zhuǎn)移到了XML布局文件中,所以增加了代碼調(diào)式的難度,可能會(huì)出現(xiàn)BUG定位困難的情況。還有,Data Binding框架是基于數(shù)據(jù)驅(qū)動(dòng)的,當(dāng)某個(gè)模塊的業(yè)務(wù)邏輯比較復(fù)雜的時(shí)候,那么Model層的數(shù)據(jù)往往會(huì)比較大。但是數(shù)據(jù)只有在頁面銷毀的時(shí)候統(tǒng)一釋放,而不能根據(jù)View的生命周期釋放,所以總的來說,項(xiàng)目占用的內(nèi)存增大了。
在這之后,谷歌在2017年Google I/O大會(huì)上宣布了一個(gè)全新的架構(gòu)組件Android Architecture Components,我們后面簡(jiǎn)稱AAC。Google官方對(duì)該框架的說明是:這是一個(gè)幫助構(gòu)建穩(wěn)定,易于測(cè)試和易于維護(hù)的App架構(gòu)的庫(kù)。該框架主要包含ViewModel、LiveData、Room三個(gè)核心組件。
1.ViewModel組件
在以往的項(xiàng)目架構(gòu)中,由于沒有ViewModel這一層,所以相關(guān)數(shù)據(jù)都存儲(chǔ)在Activity或者Fragment中,而Activity和Fragment都有自己的生命周期,在特殊的情況下會(huì)發(fā)生銷毀或者重新創(chuàng)建,這時(shí)候存儲(chǔ)在Activity或者Fragment中的數(shù)據(jù)會(huì)隨著頁面的銷毀而消失,雖然Activity 可以使用 onSaveInstanceState方法存儲(chǔ)和恢復(fù)相關(guān)的數(shù)據(jù),但是這只適用于少量的數(shù)據(jù)。AAC框架中的ViewModel組件很好地解決了這個(gè)問題,ViewModel組件旨在以注重生命周期的方式存儲(chǔ)和管理界面相關(guān)的數(shù)據(jù),它能夠承擔(dān)保存數(shù)據(jù)的責(zé)任,把數(shù)據(jù)從界面中分離出來。同時(shí),ViewModel也有自己的生命周期,和Activity、Fragment等組件的生命周期相匹配,這樣當(dāng)遇到界面銷毀重建的情況時(shí)能夠很好地保存數(shù)據(jù),然后及時(shí)地恢復(fù)到界面上。
2.LiveData 組件
LiveData 能夠感知Activity、Fragment等組件的生命周期。當(dāng)Activity等組件銷毀時(shí),LiveData也會(huì)被退訂,這樣就有效地避免部分內(nèi)存泄露問題。LiveData組件把View層和ViewModel層串聯(lián)了起來,一旦數(shù)據(jù)發(fā)生了變化,就會(huì)通知View層,界面便會(huì)做出響應(yīng)。
3.Room 組件
Room組件是在Android本地?cái)?shù)據(jù)庫(kù)基礎(chǔ)上封裝的一個(gè)組件,可以提供強(qiáng)大的數(shù)據(jù)庫(kù)功能。Room組件在MVVM架構(gòu)中不是必須的,可以根據(jù)自己項(xiàng)目的需求選擇。
我們利用AAC框架可以很輕松地搭建一個(gè)MVVM架構(gòu)的項(xiàng)目。搭建流程主要是:ViewModel組件作為MVVM架構(gòu)中的ViewModel層,Activity和XML布局文件作為View層,LiveData作為可觀察的數(shù)據(jù)存儲(chǔ)器類在ViewModel層被創(chuàng)建,在View層中被觀察,從而完成View層和ViewModel層的綁定。對(duì)比單純Data Binding框架搭建的MVVM架構(gòu),AAC框架更加地完善和合理,對(duì)于Android開發(fā)者來說更加地友好。當(dāng)然,也可以在AAC框架的基礎(chǔ)上結(jié)合Data Binding框架,這需要根據(jù)項(xiàng)目的具體情況進(jìn)行考量。
總的來說,架構(gòu)的引入目的是為了使項(xiàng)目結(jié)構(gòu)更加合理,一個(gè)合理的架構(gòu)可以使項(xiàng)目模塊內(nèi)部高聚合、模塊之間低耦合。在項(xiàng)目開發(fā)的過程中,可以讓開發(fā)人員只需要專注于某個(gè)模塊或者某個(gè)業(yè)務(wù),分工更加地合理,極大提高個(gè)人開發(fā)效率和團(tuán)隊(duì)的開發(fā)效率。架構(gòu)的引入往往并不意味著代碼量的減少,甚至可能會(huì)使代碼量增多,因?yàn)槲覀円腠?xiàng)目架構(gòu)的目的是為了項(xiàng)目在邏輯上更簡(jiǎn)單,讓整個(gè)項(xiàng)目的質(zhì)量、可擴(kuò)展性、可維護(hù)性等得到提高。MVVM架構(gòu)的諸多優(yōu)點(diǎn)可以讓項(xiàng)目穩(wěn)健性更強(qiáng)、可測(cè)試性更好、可維護(hù)性更高。