當(dāng)某個(gè)組件第一次運(yùn)行的時(shí)候,Android啟動(dòng)了一個(gè)進(jìn)程。默認(rèn)的,所有的組件和程序運(yùn)行在這個(gè)進(jìn)程和線程中。
也可以安排組件在其他的進(jìn)程或者線程中運(yùn)行
進(jìn)程
組件運(yùn)行的進(jìn)程由manifest file控制。 組件的節(jié)點(diǎn) — <activity>, <service>, <receiver>, 和 <provider> — 都包含一個(gè) process 屬性。 這個(gè)屬性可以設(shè)置組件運(yùn)行的進(jìn)程:可以配置組件在一個(gè)獨(dú)立進(jìn)程運(yùn)行,或者多個(gè)組件在同一個(gè)進(jìn)程運(yùn)行。甚至可以多個(gè)程序在一個(gè)進(jìn)程中運(yùn)行——如果這些程序共享一個(gè)User ID并給定同樣的權(quán)限 。<application> 節(jié)點(diǎn)也包含 process 屬性 ,用來(lái)設(shè)置程序中所有組件的默認(rèn)進(jìn)程。
所有的組件在此進(jìn)程的主線程中實(shí)例化 ,系統(tǒng)對(duì)這些組件的調(diào)用從主線程中分離。并非每個(gè)對(duì)象都會(huì)從主線程中分離。一般來(lái)說(shuō),響應(yīng)例如View.onKeyDown()用戶操作的方法和通知的方法也在主線程中運(yùn)行。這就表示, 組件被系統(tǒng)調(diào)用的時(shí)候不應(yīng)該長(zhǎng)時(shí)間運(yùn)行或者阻塞操作(如網(wǎng)絡(luò)操作或者計(jì)算大量數(shù)據(jù)),因?yàn)檫@樣會(huì)阻塞進(jìn)程中的其他組件 。可以把這類操作從主線程中分離。
當(dāng)更加常用的進(jìn)程無(wú)法獲取足夠內(nèi)存,Android可能會(huì)關(guān)閉不常用的進(jìn)程。下次啟動(dòng)程序的時(shí)候會(huì)重新啟動(dòng)進(jìn)程。
當(dāng)決定哪個(gè)進(jìn)程需要被關(guān)閉的時(shí)候, Android會(huì)考慮哪個(gè)對(duì)用戶更加有用。如Android會(huì)傾向于關(guān)閉一個(gè)長(zhǎng)期不顯示在界面的進(jìn)程來(lái)支持一個(gè)經(jīng)常顯示在界面的進(jìn)程。是否關(guān)閉一個(gè)進(jìn)程決 定于組件在進(jìn)程中的狀態(tài),參見(jiàn)后面的章節(jié)Component Lifecycles.
線程
即使為組件分配了不同的進(jìn)程,有時(shí)候也需要再分配線程。 比如用戶界面需要很快對(duì)用戶進(jìn)行響應(yīng),因此某些費(fèi)時(shí)的操作,如網(wǎng)絡(luò)連接、下載或者非常占用服務(wù)器時(shí)間的操作應(yīng)該放到其他線程。
線程通過(guò)java的標(biāo)準(zhǔn)對(duì)象Thread 創(chuàng)建. Android 提供了很多方便的管理線程的方法:— Looper 在線程中運(yùn)行一個(gè)消息循環(huán); Handler 傳遞一個(gè)消息; HandlerThread 創(chuàng)建一個(gè)帶有消息循環(huán)的線程。
遠(yuǎn)程調(diào)用Remote procedure calls
Android有一個(gè)遠(yuǎn)程調(diào)用(RPCs) 的輕量級(jí)機(jī)制— 通過(guò)這個(gè)機(jī)制,方法可以在本地調(diào)用,在遠(yuǎn)程執(zhí)行(在其他進(jìn)程執(zhí)行),還可以返回一個(gè)值。要實(shí)現(xiàn)這個(gè)需求,必須分解方法調(diào)用,并且所有要傳遞的數(shù)據(jù)必須是操 作系統(tǒng)可以訪問(wèn)的級(jí)別。從本地的進(jìn)程和內(nèi)存地址傳送到遠(yuǎn)程的進(jìn)程和內(nèi)存地址并在遠(yuǎn)程處理和返回。返回值必須向相反的方向傳遞。Android提供了做以上 操作的代碼,所以開(kāi)發(fā)者可以專注于實(shí)現(xiàn)RPC的接口。
一個(gè)RPC接口只能包含方法。所有的方法都是同步執(zhí)行的 (直到遠(yuǎn)程方法返回,本地方法才結(jié)束阻塞),沒(méi)有返回值的時(shí)候也是如此。
簡(jiǎn)單來(lái)說(shuō),這個(gè)機(jī)制是這樣的: 使用IDL (interface definition language)定義你想要實(shí)現(xiàn)的接口, aidl 工具可以生成用于java的接口定義,本地和遠(yuǎn)程都要使用這個(gè)定義 。它包含2個(gè)類,見(jiàn)下圖:
inner類包含了所有的管理遠(yuǎn)程程序(符合IDL描述的接口)所需要的代碼。所有的inner類實(shí)現(xiàn)了IBinder 接口.其中一個(gè)在本地使用,可以不管它的代碼;另外一個(gè)叫做Stub繼承了 Binder 類。為了實(shí)現(xiàn)遠(yuǎn)程調(diào)用,這個(gè)類包含RPC接口。開(kāi)發(fā)者可以 繼承Stub類來(lái)實(shí)現(xiàn)需要的方法 。
一般來(lái)說(shuō),遠(yuǎn)程進(jìn)程會(huì)被一個(gè)service管理(因?yàn)閟ervice可以通知操作系統(tǒng)這個(gè)進(jìn)程的信息并和其他進(jìn)程通信),它也會(huì)包含aidl 工具產(chǎn)生的接口文件,Stub類實(shí)現(xiàn)了遠(yuǎn)處那個(gè)方法。服務(wù)的客戶端只需要aidl 工具產(chǎn)生的接口文件。
以下是如何連接服務(wù)和客戶端調(diào)用:
- ·服務(wù)的客戶端(本地)會(huì)實(shí)現(xiàn)onServiceConnected() 和onServiceDisconnected() 方法,這樣,當(dāng)客戶端連接或者斷開(kāi)連接的時(shí)候可以獲取到通知。通過(guò) bindService() 獲取到服務(wù)的連接。
- · 服務(wù)的 onBind() 方法中可以接收或者拒絕連接,取決它收到的intent (intent通過(guò) bindService()方法連接到服務(wù)). 如果服務(wù)接收了連接,會(huì)返回一個(gè)Stub類的實(shí)例.
- · 如果服務(wù)接受了連接,Android會(huì)調(diào)用客戶端的onServiceConnected() 方法,并傳遞一個(gè)Ibinder對(duì)象(系統(tǒng)管理的Stub類的代理),通過(guò)這個(gè)代理,客戶端可以連接遠(yuǎn)程的服務(wù)。
以上的描述省略很多RPC的機(jī)制。請(qǐng)參見(jiàn)Designing a Remote Interface Using AIDL 和 IBinder 類。
線程安全的方法
在某些情況下,方法可能調(diào)用不止一個(gè)的線程,因此需要注意方法的線程安全。
對(duì)于可以遠(yuǎn)程調(diào)用的方法,也要注意這點(diǎn)。當(dāng)一個(gè)調(diào)用在Ibinder對(duì)象中的方法的程序啟動(dòng)了和Ibinder對(duì)象相同的進(jìn)程,方法就在 Ibinder的進(jìn)程中執(zhí)行。但是,如果調(diào)用者發(fā)起另外一個(gè)進(jìn)程,方法在另外一個(gè)線程中運(yùn)行,這個(gè)線程在和IBinder對(duì)象在一個(gè)線程池中;它不會(huì)在進(jìn) 程的主線程中運(yùn)行。例如,一個(gè)service從主線程被調(diào)用onBind() 方法,onBind() 返回的對(duì)象(如實(shí)現(xiàn)了RPC的Stub子類)中的方法會(huì)被從線程池中調(diào)用。因?yàn)橐粋€(gè)服務(wù)可能有多個(gè)客戶端請(qǐng)求,不止一個(gè)線程池會(huì)在同一時(shí)間調(diào)用 IBinder的方法。因此IBinder必須線程安全。
簡(jiǎn)單來(lái)說(shuō),一個(gè)content provider 可以接收其他進(jìn)程的數(shù)據(jù)請(qǐng)求。即使ContentResolver和ContentProvider類沒(méi)有隱藏了管理交互的細(xì) 節(jié),ContentProvider中響應(yīng)這些請(qǐng)求的方法(query(), insert(), delete(), update(), and getType() )— 是在content provider的線程池中被調(diào)用的,而不是ContentProvider的本身進(jìn)程。因?yàn)檫@些方法可能是同時(shí)從很多線程池運(yùn)行的,所以這些方法必須要 線程安全。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
