用戶界面(User Interface,UI)是系統(tǒng)和用戶之間進(jìn)行信息交換的媒介,實(shí)現(xiàn)信息的內(nèi)部形式與用戶可以接收形式之間的轉(zhuǎn)換。
在Android系統(tǒng)中,Android自帶有許多要求,預(yù)示著其用戶界面的復(fù)雜性:它是一個(gè)支持多個(gè)并發(fā)應(yīng)用程序的多處理系統(tǒng),接受多種形式的輸入,有著高交互性,必須具有足夠的靈活性,以支持現(xiàn)在和未來廣泛的設(shè)備。令人印象深刻的是豐富的用戶界面及其易用性,實(shí)現(xiàn)了所有給定的功能。但為了使用應(yīng)用程序在不同的設(shè)備上正常的顯示以及運(yùn)行,避免對系統(tǒng)性能造成過大的負(fù)擔(dān),應(yīng)該明白其工作原理。
Android使用XML文件描述用戶界面;資源文件獨(dú)立保存在資源文件夾中;對用戶界面描述非常靈活,允許不明確定義界面元素的位置和尺寸,僅聲明界面元素的相對位置和粗略尺寸。以下就來介紹一下Android的用戶界面框架。
Android是在Java環(huán)境中增加了一個(gè)圖形用戶界面(GUI)工具包,聯(lián)合了AWT,Swing,SWT,和J2ME(撇開Web UI的工具包)。Android框架和他們一樣,它是單線程的,事件驅(qū)動(dòng)的,并建立一個(gè)嵌套的組件庫。
Android用戶界面框架(Android UI Framework),像其他的UI框架一樣,采用了MVC(Model-View-Controller)模型,提供了處理用戶輸入的控制器(Controller),顯示用戶界面和圖像的視圖(View),以及保存數(shù)據(jù)和代碼的模型(Model)。

圖-1 Android用戶界面框架MVC模型
其中Model是應(yīng)用程序的核心。雖然特定應(yīng)用程序的視圖(View)和控制器(Controller)必然反映他們操縱的Model,但一個(gè)Model可能是由幾個(gè)不同的應(yīng)用使用。想想看,例如,一個(gè)MP3播放器的應(yīng)用程序以及一個(gè)將MP3文件轉(zhuǎn)換成WAV MP3文件的程序,對于這兩個(gè)應(yīng)用程序,Model包括它的MP3文件格式和編解碼器。然而,前者的應(yīng)用程序,有熟悉的停止,啟動(dòng)和暫?刂频炔僮。后者可能不會(huì)產(chǎn)生任何聲音;相反,它會(huì)設(shè)置比特率的控制等。此時(shí),他們的Model都是對所有的文件數(shù)據(jù)。
其中的控制器(Controller)能夠接收并響應(yīng)程序的外部動(dòng)作,如按鍵動(dòng)作或觸摸屏動(dòng)作等?刂破魇褂藐(duì)列處理外部動(dòng)作,每個(gè)外部動(dòng)作作為一個(gè)對應(yīng)的事件被加入隊(duì)列中,然后Android用戶界面框架按照“先進(jìn)先出”的規(guī)則從隊(duì)列中獲取事件,并將這個(gè)事件分配給所對應(yīng)的事件處理方法。例如,當(dāng)用戶按下他的手機(jī)上的鍵,Android系統(tǒng)生成的KeyEvent,并將其添加到事件隊(duì)列中。后,在之前已排隊(duì)的事件被處理后,KeyEvent是從隊(duì)列中刪除的,并作為當(dāng)前選擇View的dispatchKeyEvent方法的調(diào)用參數(shù)傳遞。一旦事件被分派到的焦點(diǎn)組件,該組件可能會(huì)采取適當(dāng)?shù)男袆?dòng)來改變程序的內(nèi)部狀態(tài)。例如,在MP3播放器應(yīng)用程序中,當(dāng)用戶點(diǎn)擊屏幕上的播放/暫停按鈕時(shí),觸發(fā)該按鈕的事件,處理方法可能更新Model,恢復(fù)播放一些先前所選樂曲。
視圖(View)是應(yīng)用程序給用戶的反饋。它負(fù)責(zé)應(yīng)用程序的部分渲染顯示,發(fā)送音頻揚(yáng)聲器,產(chǎn)生觸覺反饋等。視圖部分應(yīng)用視圖樹(View Tree)模型。視圖樹是由Android用戶界面框架中的界面元素以一種樹形結(jié)構(gòu)組織在一起的,Android系統(tǒng)會(huì)依據(jù)視圖樹的結(jié)構(gòu)從上至下繪制每一個(gè)界面元素。每個(gè)元素負(fù)責(zé)對自身的繪制,如果元素包含子元素,該元素會(huì)通知其下所有子元素進(jìn)行繪制。
下面就來詳細(xì)介紹一下視圖樹。Android 當(dāng)中的可視化界面單元,可分為“容器”與“非容器”兩類,容器類繼承ViewGroup,非容器類則從 View 衍生出來,如圖-2所示。

圖-2 Android視圖樹(View Tree)
視圖樹由View和ViewGroup構(gòu)成。其中,View是界面的基本的可視單元,存儲(chǔ)了屏幕上特定矩形區(qū)域內(nèi)所顯示內(nèi)容的數(shù)據(jù)結(jié)構(gòu),并能夠?qū)崿F(xiàn)所占據(jù)區(qū)域的界面繪制、焦點(diǎn)變化、用戶輸入和界面事件處理等功能。同時(shí)View也是一個(gè)重要的基類,所有在界面上的可見元素都是View的子類。ViewGroup是一種能夠承載含多個(gè)View的顯示單元,它承載了界面布局,同時(shí)還承載了具有原子特性的重構(gòu)模塊。
如圖-3所示,這些 Layout 可以套疊式地組成一棵視圖樹。其中,父節(jié)點(diǎn)的 Layout 與子節(jié)點(diǎn)的 LayoutParams之間有控制關(guān)系,例如,若父節(jié)點(diǎn)是RelativeLayout,則子節(jié)點(diǎn)的單元中可以指定RelativeLayout.LayoutParams 中的屬性,以控制子節(jié)點(diǎn)在父節(jié)點(diǎn)中的排列狀況。

圖-3 ViewGroup樹形層次結(jié)構(gòu)
在單線程用戶界面中,控制器從隊(duì)列中獲取事件和視圖在屏幕上繪制用戶界面,使用的都是同一個(gè)線程。這樣的單線程用戶界面使得處理方法具有順序性,能夠降低應(yīng)用程序的復(fù)雜程度,同時(shí)也能降低開發(fā)的難度。
注:單線程用戶界面存在缺點(diǎn)是:如果事件處理方法過于復(fù)雜,可能會(huì)導(dǎo)致用戶界面失去響應(yīng)。