5 Basic Components 1. Activity 2. Service 3. Broadcast Receiver 4. Content Provider 5. Intent
Activity —— 應(yīng)用表示層( 基類 Activity ) 應(yīng)用程序中的每個(gè)屏幕都是通過繼承和擴(kuò)展基類 Activity 來實(shí)現(xiàn)的。 同一應(yīng)用中的每個(gè) Activity 是相互獨(dú)立的。程序啟動(dòng)后顯示的第一幅畫面是應(yīng)用程序的第一個(gè) Activity (默認(rèn)窗口),而后可以根據(jù)需要從這個(gè) Activity 啟動(dòng)另一個(gè)新的 Activity 。 Activity 利用 View 來實(shí)現(xiàn)應(yīng)用中的 GUI (用戶直接通過 GUI 和應(yīng)用程序做交互)。 Activity 窗口內(nèi)的可見內(nèi)容通過基類 View 提供。使用 Activity.setContentView() 方法設(shè)置當(dāng)前 Activity 中的 View 對(duì)象。 l 每個(gè) View 對(duì)象控制著窗口內(nèi)的一個(gè)矩形空間; l View 是一種層次化結(jié)構(gòu), Parent View 中的布局屬性會(huì)被子 View 繼承; l 位于 View 層次關(guān)系最底層的子 View 對(duì)象所代表的矩形空間就是跟用戶進(jìn)行交互的地方
Activity 狀態(tài)回調(diào): l onCreate l onStart l onRestart l onResume l onPause l onStop l onDestroy
Service —— 沒有可見的用戶界面,但能夠長時(shí)間運(yùn)行于后臺(tái)( 基類 Service ) 運(yùn)行于應(yīng)用程序進(jìn)程的主線程中,因此 Service 不會(huì)阻塞其他組件和用戶界面。 Service 是不能自己啟動(dòng)的,必須通過 Context 對(duì)象(如一個(gè) Activity )調(diào)用 startService 或 bindService 方法來啟動(dòng)(用這兩種方法啟動(dòng)的 Service 的生命周期不同)。 1. 調(diào)用 startService 方法 a) 若 Service 沒有啟動(dòng),則首先會(huì)調(diào)用該 Service 的 onCreate 方法,然后再調(diào)用 onStart 方法。 b) 若 Service 已經(jīng)啟動(dòng),則會(huì)直接調(diào)用 onStart 方法 c) 該方法啟動(dòng)的 Service ,可以通過 Context 對(duì)象調(diào)用 stopService 來關(guān)閉,也可以通過 Service 自身調(diào)用 stopSelf() 或 stopSelfResult() 來關(guān)閉,關(guān)閉之前調(diào)用 onDestory 方法。 2. 調(diào)用 bindService 方法,使當(dāng)前 Context 對(duì)象通過一個(gè) ServiceConnection 的對(duì)象綁定到所指定的 Service a) 若 Service 沒有啟動(dòng),則首先會(huì)調(diào)用該 Service 的 onCreate 方法初始化啟動(dòng),然后調(diào)用 Service 的 onBind 方法初始化綁定。 b) 如果綁定 Service 的 Context 對(duì)象被銷毀時(shí),被綁定的 Service 也會(huì)調(diào)用 onUnbind 和 onDestroy 方法停止運(yùn)行 c) 注意: BroadcastReceiver 是不能綁定服務(wù)的。 d) 一個(gè)綁定 Service 的 Context 對(duì)象還可以通過 unbindService() 來取消對(duì)服務(wù)的綁定。 e) 取消時(shí), Service 會(huì)調(diào)用 unbind 方法,若 Service 是通過 bindService 來啟動(dòng)的,還會(huì)調(diào)用 onDestroy 方法來停止服務(wù)。 Service 狀態(tài)回調(diào): l onCreate l onStart l onBind l onRebind l onUnbind l onDestroy
Broadcast Receiver —— 用戶接收廣播通知的組件( 基類 BroadcastReceiver ) Android 中的廣播要么來自于系統(tǒng),要么來自普通應(yīng)用程序。 很多事件都可能導(dǎo)致系統(tǒng)廣播,如手機(jī)所在時(shí)區(qū)發(fā)生變化,電池電量低,用戶改變系統(tǒng)語言設(shè)置等。 來自普通應(yīng)用程序,如一個(gè)應(yīng)用程序通知其他應(yīng)用程序某些數(shù)據(jù)已經(jīng)下載完畢。 為了響應(yīng)不同的事件通知,應(yīng)用程序可以注冊(cè)不同的 Broadcast Receiver 。所有的 Broadcast Receiver 都繼承自基類 BroadcastReceiver 。 BroadcastReceiver 自身并不實(shí)現(xiàn)圖形用戶界面,但是當(dāng)它收到某個(gè)通知后, BroadcastReceiver 可以啟動(dòng) Activity 作為響應(yīng),或者通過 NotificationMananger 提醒用戶。 BroadcastReceiver 是對(duì)發(fā)送出來的 Broadcast 進(jìn)行過濾接收并響應(yīng)的一類組件。
發(fā)送 Broadcast 信息 1. 把要發(fā)送的信息和用于過濾得信息 ( 如 Action 、 Category) 裝入一個(gè) Intent 對(duì)象 2. 調(diào)用 Context. sendBroadcast() 、 sendOrderBroadcast() 、 sendStickyBroadcast() 方法,廣播該 Intent 對(duì)象 3. 使用 sendBroadcast() 或 sendStickyBroadcast() 方法發(fā)出去的 Intent ,所有滿足條件的 BroadcastReceiver 都會(huì)隨機(jī)地執(zhí)行其 onReceive() 方法; 4. 而 sendOrderBroadcast() 發(fā)出去的 Intent ,會(huì)根據(jù) BroadcastReceiver 注冊(cè)時(shí) IntentFilter 設(shè)置的優(yōu)先級(jí)的順序來執(zhí)行,相同優(yōu)先級(jí)的 BroadcastReceiver 則是隨機(jī)執(zhí)行 5. sendStickyBroadcast() 方法主要的不同是, Intent 在發(fā)送后一直存在,并且在以后調(diào)用 registerReceiver() 注冊(cè)相匹配的 Intent 時(shí)會(huì)把這個(gè) Intent 直接返回。 6. 若在使用 sendBroadcast() 方法時(shí)指定了接收的權(quán)限,這只有在 AndroidManifest.xml 中用 <uses-permission> 標(biāo)簽聲明了擁有此權(quán)限的 BroadcastReceiver 才會(huì)有可能接收到發(fā)送來 Broadcast 。 7. 若在注冊(cè) BroadcastReciever 時(shí),指定了可接收的 Broadcast 的權(quán)限,則只有在包內(nèi)的 AndroidManifest.xml 中用 <uses-permission> 標(biāo)簽聲明了,擁有此權(quán)限的 Context 對(duì)象所發(fā)送的 Broadcast 才有可能被這個(gè) BroadcastReceiver 所接收。 接收 Broadcast 消息 1. 繼承 BroadcastReceiver 類,并實(shí)現(xiàn) onReceive 方法 2. 注冊(cè) Broadcast Receiver (有 2 種方法:一種方法是,靜態(tài)地在 AndroidManifest.xml 中用 <receiver> 標(biāo)簽聲明,并在標(biāo)簽內(nèi)用 <intent-filter> 標(biāo)簽設(shè)置過濾器; 另一種方法,動(dòng)態(tài)地在代碼中先定義并設(shè)置好一個(gè) IntentFilter 對(duì)象,然后再需要注冊(cè)的地方調(diào)用 Context.registerReceiver() 方法) (取消注冊(cè)時(shí),調(diào)用 Context.unregisterReceiver() 方法)
Content Provider —— 為解決應(yīng)用程序間數(shù)據(jù)通信、共享的問題( 基類 ContentProvider ) 在 Android 中,每個(gè)應(yīng)用程序都是用自己的用戶 ID 并在自己的進(jìn)程中運(yùn)行。這樣的好處是,可以有效地保護(hù)系統(tǒng)及應(yīng)用程序,避免被其他不正常德應(yīng)用程序所影響,每個(gè)進(jìn)程都擁有獨(dú)立的進(jìn)程地址空間和虛擬空間。 Content Provider 可以將應(yīng)用程序特定的數(shù)據(jù)提供給另一個(gè)應(yīng)用程序使用。其數(shù)據(jù)存儲(chǔ)方式可以是 Android 文件系統(tǒng)、 SQLite 數(shù)據(jù)庫或者其他合理的方式。 當(dāng)數(shù)據(jù)需要在應(yīng)用程序間共享時(shí),我們就可以利用 ContentProvider 為數(shù)據(jù)定義一個(gè) URI 。之后,其他應(yīng)用程序?qū)?shù)據(jù)進(jìn)行查詢或者修改時(shí),只需要從當(dāng)前上下文對(duì)象獲得一個(gè) ContentResolver, 然后傳入響應(yīng)的 URI 就可以了。 Content Provider 繼承自基類 ContentProvider ,并且實(shí)現(xiàn)了一組標(biāo)準(zhǔn)接口。通過這組接口,其他應(yīng)用程序能對(duì)數(shù)據(jù)進(jìn)行讀寫和存儲(chǔ)。然而,需要使用數(shù)據(jù)的應(yīng)用程序并不是直接調(diào)用這組方法,而是通過調(diào)用 ContentResolver 對(duì)象的方法來完成。 ContentResolver 對(duì)象可以與任意 ContentProvider 通信。 要為當(dāng)前應(yīng)用程序的私有數(shù)據(jù)定義 URI ,就需要專門定義一個(gè)繼承自 ContentProvider 的類,然后根據(jù)不同的操作調(diào)用的方法去實(shí)現(xiàn)這些方法的功能。 ContentResolver 類為應(yīng)用程序提供了接入 Content 機(jī)制的方法。要構(gòu)造一個(gè) ContentResolver 對(duì)象可以為構(gòu)造方法 ContentResolver(Context context) 傳入一個(gè) Context 對(duì)象,也可以直接通過 Context 對(duì)象調(diào)用 getContentResolver() 方法獲得 —— 有的 ContentResolver 對(duì)象后,就可以通過調(diào)用其 query() 、 insert() 、 update() 等方法來對(duì)數(shù)據(jù)進(jìn)行操作了。
一旦需要以上 4 種 Android 應(yīng)用程序基本組件完成請(qǐng)求, Android 會(huì)首先確認(rèn)該組件所在進(jìn)程是否運(yùn)行,如果沒有運(yùn)行, Android 將先啟動(dòng)進(jìn)程,同時(shí)確認(rèn)被請(qǐng)求組件的實(shí)例是否存在,否則將創(chuàng)建一個(gè)新的組件實(shí)例。
Intent —— 連接組件的紐帶 以上 4 種基本組件中,除了 Content Provider 是通過 Content Resolver 激活外,其他 3 種組件 Activity 、 Service 和 Broadcast Receiver 都是由 Intent 異步消息激活的。 Intent 在不同的組件之間傳遞消息,將一個(gè)組件的請(qǐng)求意圖傳給另一個(gè)組件。因此, Intent 是包含具體請(qǐng)求信息的對(duì)象。 針對(duì)不同的組件, Intent 所包含的消息內(nèi)容有所不同,且不同組件的激活方式也不同, 且不同類型組件有傳遞 Intent 的不同方式。 Intent 是一種運(yùn)行時(shí)綁定( runtime binding )機(jī)制,它能夠在程序運(yùn)行的過程中連接兩個(gè)不同的組件。通過 Intent ,你的程序可以向 Android 表到某種請(qǐng)求或者意愿, Android 會(huì)根據(jù)意愿的內(nèi)容選擇適當(dāng)?shù)慕M件來處理請(qǐng)求。 l 激活一個(gè)新的 Activity ,或者讓一個(gè)現(xiàn)有的 Activity 執(zhí)行一個(gè)新的操作,可以通過調(diào)用如下兩種方法 ( 這兩匯總方法需要傳入的 Intent 參數(shù)稱為 Activity Action Intent) : 1. Context.startActivity() 2. Activity.startActivityForResult() l 啟動(dòng)一個(gè)新的服務(wù),或者向一個(gè)已有的服務(wù)傳遞新的指令,可以調(diào)用如下兩種方法: 1. Context.startService() 2. Context.bindService() l 發(fā)送廣播 Intent( 所有已注冊(cè)的擁有與之相匹配 IntenFilter 的 BroadcastReceiv 就會(huì)被激活 ) ,可以調(diào)用如下三種方法: 1. Context.sendBroadcast() 2. Context.sendOrderBroadcast() 3. Context.sendStickBroadcast() Intent 一旦發(fā)出, Android 都會(huì)準(zhǔn)確找到相匹配的一個(gè)或多個(gè) Activity 、 Service 或 BroadcastReceiver 作響應(yīng)。所以,不同類型的 Intent 消息不會(huì)出現(xiàn)重疊, BroadcastIntent 消息只會(huì)發(fā)送給 BroadcastReceiver ,而絕不可能發(fā)送給 Activity 或 Server 。有 startActivity() 傳遞的消息也只可能發(fā)送給 Activity ,由 startService() 傳遞的 Intent 只可能發(fā)送給 Service 。
Intent 對(duì)象抽象地描述了執(zhí)行操作, Intent 的主要組成部分; 1. 目標(biāo)組件名稱。 [ 可選項(xiàng) ] a) 組件名稱是一個(gè) ComponentName 對(duì)象,是目標(biāo)組件類名和目標(biāo)組件所在應(yīng)用程序包的組合 b) 組件中的包名不一定要和 manifes 文件中包名完全匹配 c) 如果 Intent 消息中指明了目標(biāo)組件的名稱,這就是一個(gè)顯示消息, Intent 會(huì)傳遞給指明的組件。 d) 如果目標(biāo)組件名稱并沒有指定, Android 則通過 Intent 內(nèi)的其他信息和已注冊(cè)的 IntentFilter 的比較來選擇合適的目標(biāo)組件 2. Action [ 隱式比較 ] a) 描述 Intent 所觸發(fā)動(dòng)作的名字字符串。 b) 理論上 Action 可以為任何字符串,而與 Android 系統(tǒng)應(yīng)用有關(guān)的 Action 字符串以靜態(tài)字符串常量的形式定義在了 Intent 類中。 3. Data [ 隱式比較 ] a) 描述 Intent 要操作的的數(shù)據(jù)的 URI 和數(shù)據(jù)類型。 b) 正確設(shè)置 Intent 的數(shù)據(jù)對(duì)于 Android 尋找系統(tǒng)中匹配 Intent 請(qǐng)求的組件很重要。 4. Category [ 隱式比較 ] a) 是對(duì)被請(qǐng)求組件的額外描述信息。 b) Android 也在 Intent 類中定義了一組靜態(tài)字符串常量表示 Intent 不同的類別。 5. Extra a) 當(dāng)我們使用 Intent 連接不同組件時(shí),有時(shí)需要在 Intent 中附加額外的信息,以便將數(shù)據(jù)傳遞給目標(biāo) Activity 。 b) Extra 用鍵值對(duì)結(jié)構(gòu)保存在 Intent 對(duì)象當(dāng)中, Intent 對(duì)象通過調(diào)用方法 putExtras() 和 getExtras() 來存儲(chǔ)和獲取 Extra c) Extra 是以 Bundle 對(duì)象的形式來保存的, Bundle 對(duì)象提供了一系列 put 和 get 方法來設(shè)置、提取相應(yīng)鍵值信息。 d) 在 Intent 類中同樣為 Android 系統(tǒng)應(yīng)用的一些 Extra 的鍵值定義了靜態(tài)字符串常量。 6. Flag
決定 Intent 目標(biāo)組件的因素: n 在顯式 Intent 消息中,決定目標(biāo)組件的唯一要素就是組件名稱(不用再定義其他 Intent 內(nèi)容) n 而隱式 Intent 消息中,由于沒有目標(biāo)組件名稱,所以必須由 Android 系統(tǒng)幫助應(yīng)用程序?qū)ふ遗c Intent 請(qǐng)求意圖最匹配的組件。 n 隱式 Intent 消息中目標(biāo)組件具體選擇方法是: android 將 Intent 的請(qǐng)求內(nèi)容和一個(gè)叫做 IntentFilter 的過濾器比較, IntentFilter 中包含系統(tǒng)中所有可能的待選組件。如果 IntentFilter 中某一個(gè)組件匹配隱式 Intent 請(qǐng)求內(nèi)容,那么 Android 就選擇該組件作為該隱式 Intent 的目標(biāo)組件。
IntenFilter 應(yīng)用程序的組件為了告訴 Android 自己能響應(yīng)、處理哪些隱式 Intent 請(qǐng)求,可以聲明一個(gè)甚至多個(gè) IntentFilter 。 每個(gè) IntentFilter 描述該組件所能響應(yīng) Intent 請(qǐng)求的能力 —— 組件希望接收什么類型的請(qǐng)求行為,什么類型的請(qǐng)求數(shù)據(jù)。 隱式 Intent 和 IntentFilter 進(jìn)行比較時(shí)的三要素: Action 、 Data 、 Category 。 一個(gè)隱式 Intent 請(qǐng)求要能夠傳遞給目標(biāo)組件,必需通過以上三個(gè)方面的檢查。如果任何一方面不匹配, Android 都不會(huì)將該隱式 Intent 傳遞給目標(biāo)組件。 <intent-filter> <action android:name=””/> <category android:name=””/> <data android:type=”” android:scheme=”” android:authority=”” android:path=””/> </intent-filter> 1. 動(dòng)作測(cè)試 a) 一條 <intent-filter> 中至少應(yīng)該包含一個(gè) <action>, 否則任何 Intent 請(qǐng)求都不能和該 <intent-filter> 匹配。 b) 如果 IntentFilter 中沒有包含任何 Actino 類型,那么無論什么 Intent 請(qǐng)求都無法和這條 IntentFilter 匹配。 c) 如果 Intent 請(qǐng)求中沒有設(shè)定 Action 類型,那么只要 IntentFilter 中包含有 Action 類型,這個(gè) Intent 請(qǐng)求將順利通過 IntentFilter 的測(cè)試。 2. 類別測(cè)試 a) 只有當(dāng) Intent 請(qǐng)求中所有的 Category 與組件中的某一個(gè) IntentFilter 的 category 完全匹配,才會(huì)讓該 Intent 請(qǐng)求通過測(cè)試, IntentFilter 中的多余 category 聲明并不會(huì)導(dǎo)致匹配失敗。 b) 一個(gè)沒有指定任何類別的 IntentFilter 僅僅只會(huì)匹配沒有設(shè)置類別的 Intent 請(qǐng)求。 3. 數(shù)據(jù)測(cè)試 a) <data> 元素指定了希望接受的 Intent 請(qǐng)求的數(shù)據(jù) URI 和數(shù)據(jù)類型: URI 被分成三部分類進(jìn)行匹配, scheme 、 authority 和 path. b) 使用 setData 設(shè)定的 Intent 請(qǐng)求的 URI 數(shù)據(jù)類型和 scheme ,必須與 IntentFilter 中指定的一致 若 IntentFilter 中還指定了 authority 或 path ,他們也需要相匹配才會(huì)通過測(cè)試。 |
|