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ū)ふ遗cIntent請(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è)試。
聯(lián)系客服