天天看點

《Android和PHP開發最佳實踐》一2.4 Android系統四大元件

之前我們已經學習了android應用架構的四大核心要點,對android的應用架構有了一個總體性的了解,接下來我們要學習android應用程式中的四個重要組成部分,也就是我們一般所說的“應用元件”。在前面講解四大核心要點的篇幅中,我們曾經提到了控件(view控件)的概念,現在我們再來學習一下android應用架構中的元件的概念。那麼何謂元件呢?顧名思義,元件當然要比控件複雜,簡而言之,元件是用于工業化組裝的部件。要達到元件的标準,必須符合三個要求,以下我們結合android應用架構讨論如下。

有統一标準

這點應該是形成元件的前提條件,試問,元件如果沒有标準,如何組裝?在這點上,android應用架構中定義了很多标準接口,滿足了元件間的各種接口需求;換一種說法,整合android系統都是按照接口規範設計出來的。

可獨立部署

元件應該是獨立的,每個元件都有自成一套的功能體系,否則就沒有形成元件的必要。比如每個activity都是可以獨立構造的,使用activity元件,我們可以完成一個包含許多複雜功能的界面;而使用service,我們可以操作一個獨立的背景程序等。

可組裝整合

可組裝是元件最重要的特性,一個完整的android應用必然是若幹個系統元件構成的,這就要求元件必須是能組裝在一起的,至于如何組裝,我們會在後面的章節中結合執行個體進行介紹。

通常來講,android應用架構中包含了四大元件:活動(activity)、服務(service)、廣播接收器(broadcast receiver)和内容提供者(content provider)。這四大元件除了具有前面所提到的三個特點之外,還有着相同的顯著特點,那就是它們都可以在android的基礎配置檔案,即androidmanifest.xml中進行配置。下面我們就來學習android系統四大元件的基本概念和使用方法。

在2.3.1節中,我們已經介紹了android活動(activity)的生命周期以及基本行為,大家應該對activity的概念有了一定的了解。此外,activity同時還是android系統四大元件中的一員,是以,本節将着重介紹activity作為元件的一般聲明方法。

說到activity的聲明方法,我們必須先了解android全局配置檔案androidmanifest.xml的基礎知識。每個android應用項目都會有自己的全局配置檔案,該檔案包含了應用的系統常量、系統權限以及所含元件等配置資訊。配置使用範例如代碼清單2-4所示。

代碼清單 2-4

從上述配置使用範例中,我們可以看到在androidmanifest.xml配置檔案範例的根元素下面有兩種标簽,即和元素。前者是應用配置的根元素,而後者則用于配置應用的權限。這裡順便說一下,每個android應用都必須事先聲明應用需要的權限,比如是否需要網絡、是否需要使用攝像頭或者是否需要打開衛星定位(gps)等。而使用者在安裝該應用之前,系統會先提示使用者是否允許該應用使用這些權限,如果使用者覺得應用不安全便可以選擇不安裝,這在一定程度上也提高了android系統的安全性。

另外,我們還可以看到,在以上配制檔案中的元素裡面含有一個或者若幹個元素,這個就是我們需要重點了解的activity标簽了。首先,我們來看一下該标簽内部的一些常用的配置選項。

android:name:表示該activity對應的類的名稱,在代碼清單2-4中,我們就定義了一個activity,它的具體類包名就是“com.app.android.helloactivity”。

android:theme:表示activity所使用的主題,在android系統中是允許我們自定義主題的(這部分的内容我們在後面章節的執行個體中會介紹到),在代碼清單2-4中,使用的是預設主題“@android:style/theme.notitlebar.fullscreen”,也就是全屏模式。

android:launchmode:activity的行為模式,之前在2.3.4節中介紹過該标簽的4種選項,即與任務行為有關的standard、singletop、singletask以及singleinstance。

android:screenorientation:表示螢幕的方向,在代碼清單2-4中,landscape表示的是該activity是橫屏顯示的,如果改成portrait的話,則就變成豎屏顯示。

當然,activity标簽可配置的選項遠不止以上這些,更詳細的使用說明可以參考7.1.2節的内容,使用範例可參考代碼清單7-11。此外,從上面的配制檔案中我們還可以看到不止一個元素。關于這點,實際上,前面我們已經介紹過消息過濾器的用法,如果大家有疑問的話,可以參考2.3.2節中與消息(intent)相關的内容。

另外,activity在應用開發中被用做控制界面的邏輯,也就是mvc中的controller控制器,關于android應用中mvc的概念可參考5.2.3節中的内容。開發者可以根據需要,在activity的生命周期方法中添加不同的邏輯來控制對應應用界面的顯示、動作和響應等,而activity類的具體用法和代碼示例我們可以在本書第7章的“微網誌執行個體”代碼中學習到。

android系統中的service服務元件和windows系統中的背景服務有點類似,這個概念應該很容易了解,比如,我們在退出某些聊天軟體之後還是可以接收到好友發來的消息,就是使用android服務元件來實作的。此外,如果需要在應用背景運作某些程式,service服務元件也絕對是最佳的選擇。另外,值得注意的是,service和之前的activity一樣,也有自己的生命周期,但是,service的生命周期相對簡單一些,如圖2-6所示。

從圖2-6中我們可以看出android服務(service)主要有以下兩種運作模式。

獨立運作模式:我們一般通過“startservice()”方法來啟動一個獨立的服務,在這種模式下,該服務不會傳回任何資訊給啟動它的程序,程序的動作結束後會自動結束。比如,浏覽器下載下傳就屬于獨立服務。

綁定運作模式:與獨立服務不同,綁定服務是與啟動它的應用綁定在一起的,當該應用結束的時候,綁定服務也會停止。另外,這種服務可以和應用中的其他子產品進行資訊互動,甚至進行程序通信(ipc)。

《Android和PHP開發最佳實踐》一2.4 Android系統四大元件

與activity類似,oncreate和ondestroy分别是android服務建立和銷毀過程中的回調方法。與獨立運作模式相比,綁定運作模式中多出來onbind和onunbind兩個函數,分别是服務綁定和解綁過程的回調方法。在android應用開發的時候,我們通常會使用startservice方法來開啟service服務。另外,在應用開發的時候千萬别忘了我們必須事先在全局配置檔案中進行如下聲明,如代碼清單2-5所示。

代碼清單 2-5

了解android服務(service)時要特别注意,千萬不要盲目認為服務是一個獨立的程序或者線程。實際上,它和應用程式的程序之間存在着複雜的聯系,是以如果我們需要在service中做一些耗時操作的話,必須新起一個線程并使用消息處理器handler來處理消息。另外,android服務的程序間通信(ipc)功能還涉及aidl(android interface definition language,android接口定義語言),有興趣的話盡管去了解一下。關于service的具體使用執行個體,大家可以先去看看android sdk中api demos裡面的remoteservice實作,本書後面的執行個體中我們也會穿插介紹。

小貼士:handler是消息處理器,用于接受子線程的消息進行處理并配合主線程更新ui界面,具體内容可參考5.2.2節中界面基礎類baseui的相關内容。

在android系統中,service服務類的使用方法比較簡單,執行service對象的start方法就可以開啟一個服務。實際上,第7章的“微網誌執行個體”中也有與service服務相關的代碼執行個體,請參考7.5.4節。

廣播接收器(broadcast receiver)是android系統的重要元件之一,可以用來接收其他應用發出來的廣播,這樣不僅增強了android系統的互動性,而且能在一定程度上提高使用者的操作體驗。比如,你在把玩應用或者遊戲的同時也可以随時接收一條短信或者一個電話,或者你在打開網頁的同時還可以接收短信驗證碼等。

廣播接收器的使用也很簡單,和其他元件的步驟一樣:先聲明,再調用。代碼清單2-6就是一個聲明廣播接收器的例子。

代碼清單 2-6

這裡我們定義了一個名為helloreceiver的廣播接收器。這個類裡面隻有一個onreceive方法,裡面我們可以定義需要的操作。使用的時候,我們可以在activity中直接使用sendbroadcast方法來發送廣播消息,這樣helloreceiver就會接收到我們發送的資訊并進行相應的處理。這裡需要注意的是,廣播接收器也是在應用主線程裡面的,是以我們不能在這裡做一些耗時的操作,如果需要的話,可以新開線程來解決。發送廣播消息的範例如代碼清單2-7所示。

代碼清單 2-7

而接收消息的使用範例,也就是廣播接收器類helloreceiver的邏輯實作,我們可以參考代碼清單2-8。

代碼清單 2-8

另外,我們需要了解,android系統中的廣播消息是有等級的,可分為普通廣播(normal broadcasts)和有序廣播(ordered broadcasts)兩種。前者是完全異步的,可以被所有的接收者接收到,而且接收者無法終止廣播的傳播;而有序廣播則是按照接收者的優先級别被依次接收到。優先級别取決于intent-filter元素的android:priority屬性,數越大,優先級越高。至于使用,我們通常會在onresume事件中通過registerreceiver進行注冊,在onpause等事件中登出,這種方式使其能夠在運作期間保持對相關事件的關注。常見的廣播事件有:短信廣播、電量通知廣播等。

在android應用中,我們可以使用顯式消息(explicit intent)來直接通路其他應用的activity,但是這僅限于activity的範疇;如果需要使用其他應用的資料,還需要用到另外一種元件,這就是所謂的内容提供者(content provider)。

顧名思義,内容提供者就是android應用架構提供的應用之間的資料提供和交換方案,它為所有的應用開了一扇窗,應用可以使用它對外提供資料。每個content provider類都使用uri(universal resource identifier,通用資源辨別符)作為獨立的辨別,格式如:content://xxx。其格式類似于rest,但是比rest更靈活,因為在調用接口的時候還可以添加projection、selection、orderby等參數,結果以cursor的模式傳回。content provider的聲明寫法非常簡單,示例可參考代碼清單2-9。

代碼清單 2-9

關于content provider的類實作,我們隻需要繼承contentprovider接口并實作其中的抽象方法即可,這幾個方法有點類似于資料操作對象dao的抽象方法,其中包括insert、delete、query和update這些常見的“增删查改”的接口方法。對于具體的資料存儲來說,一般會使用android的内置資料庫sqlite,當然也可以采用檔案或者其他形式的混合資料來實作。關于android系統中的資料存儲我們會在2.6節中介紹。

我們在使用上述四大元件的時候還需要注意的是:實際上,service和content provider都可用于ipc(inter-process communication,程序間通信),也就是在多個應用之間進行資料交換。service可以是異步的,而content provider則是同步的。在某些情況下,在設計的時候我們要考慮到性能問題。當然,android也提供了一個asyncqueryhandler幫助異步通路content provider。關于以上四大元件的具體使用,我們會在後面的章節中穿插介紹。

另外,與content provider配合使用的還有content resolver,即内容處理器。前面也提到了content provider是以資料庫接口的方式将資料提供出去,那麼content resolver也将采用類似的資料庫操作來從content provider中擷取資料,而擷取資料就需要使用query接口。和content provider類似,content resolver也需要使用uri的方式來擷取對應的内容,其使用範例可參考7.3.2節中提到的httputil類的相關代碼(代碼清單7-34)。