1. Android中進(jìn)程與進(jìn)程、線(xiàn)程與線(xiàn)程之間如何通信?
1)一個(gè) Android 程序開(kāi)始運(yùn)行時(shí),會(huì)單獨(dú)啟動(dòng)一個(gè)Process。
默認(rèn)情況下,所有這個(gè)程序中的Activity或者Service都會(huì)跑在這個(gè)Process。
默認(rèn)情況下,一個(gè)Android程序也只有一個(gè)Process,但一個(gè)Process下卻可以有許多個(gè)Thread。
2)一個(gè) Android 程序開(kāi)始運(yùn)行時(shí),就有一個(gè)主線(xiàn)程Main Thread被創(chuàng)建。該線(xiàn)程主要負(fù)責(zé)UI界面的顯示、更新和控件交互,所以又叫UI Thread。
3)一個(gè)Android程序創(chuàng)建之初,一個(gè)Process呈現(xiàn)的是單線(xiàn)程模型--即MainThread,所有的任務(wù)都在一個(gè)線(xiàn)程中運(yùn)行,所以,MainThread所調(diào)用的每一個(gè)函數(shù),其耗時(shí)應(yīng)該越短越好,而對(duì)于比較耗時(shí)的工作,應(yīng)該交給子線(xiàn)程去做,以避免主線(xiàn)程(UI線(xiàn)程)被阻塞,導(dǎo)致程序出現(xiàn)ANR(Application not response)
一個(gè)Activity就運(yùn)行在一個(gè)線(xiàn)程中嗎?或者編碼時(shí),如果不是明確安排在不同線(xiàn)程中的兩個(gè)Activity,其就都是在同一個(gè)線(xiàn)程中?那從一個(gè)Activity跳轉(zhuǎn)到另一個(gè)Activity時(shí),是不是跳出的那個(gè)Activity就處在睡眠狀態(tài)了?
【答】 每個(gè)Activity都有一個(gè)Process屬性,可以指定該Activity是屬于哪個(gè)進(jìn)程的。當(dāng)然如果不明確指明,應(yīng)該就是從屬于默認(rèn)進(jìn)程(Application指定的,如其未指定,應(yīng)該就是默認(rèn)主進(jìn)程)。
Android中有Task的概念,而同一個(gè)Task的各個(gè)Activity會(huì)形成一個(gè)棧,只有站定的Activity才有機(jī)會(huì)與用戶(hù)交互。
原文地址:Android中的進(jìn)程與線(xiàn)程 原文作者:江鵬
當(dāng)應(yīng)用程序的組件第一次運(yùn)行時(shí),Android將啟動(dòng)一個(gè)只有一個(gè)執(zhí)行線(xiàn)程的Linux進(jìn)程。默認(rèn),應(yīng)用程序所有的組件運(yùn)行在這個(gè)進(jìn)程和線(xiàn)程中。然而,你可以安排組件運(yùn)行在其他進(jìn)程中,且你可以為進(jìn)程衍生出其它線(xiàn)程。本文從下面幾點(diǎn)來(lái)介紹Android的進(jìn)程與線(xiàn)程:
1、進(jìn)程
組件運(yùn)行于哪個(gè)進(jìn)程中由清單文件控制。組件元素——<activity>、<service>、<receiver>、<provider>,都有一個(gè)process屬性可以指定組件運(yùn)行在哪個(gè)進(jìn)程中。這個(gè)屬性可以設(shè)置為每個(gè)組件運(yùn)行在自己的進(jìn)程中,或者某些組件共享一個(gè)進(jìn)程而其他的不共享。他們還可以設(shè)置為不同應(yīng)用程序的組件運(yùn)行在同一個(gè)進(jìn)程中——假設(shè)這些應(yīng)用程序共享同一個(gè)Linux用戶(hù)ID且被分配了同樣的權(quán)限。<application>元素也有process屬性,為所有的組件設(shè)置一個(gè)默認(rèn)值。
所有的組件都在特定進(jìn)程的主線(xiàn)程中實(shí)例化,且系統(tǒng)調(diào)用組件是由主線(xiàn)程派遣。不會(huì)為每個(gè)實(shí)例創(chuàng)建單獨(dú)的線(xiàn)程,因此,對(duì)應(yīng)這些調(diào)用的方法——諸如View.onKeyDown()報(bào)告用用戶(hù)的行為和生命周期通知,總是運(yùn)行在進(jìn)程的主線(xiàn)程中。這意味著,沒(méi)有組件當(dāng)被系統(tǒng)調(diào)用時(shí)應(yīng)該執(zhí)行很長(zhǎng)時(shí)間或阻塞操作(如網(wǎng)絡(luò)操作或循環(huán)計(jì)算),因?yàn)檫@將阻塞進(jìn)程中的其它組件。你可以為長(zhǎng)操作衍生獨(dú)立的線(xiàn)程。
public boolean onKeyDown(int keyCode,KeyEvent event):默認(rèn)實(shí)現(xiàn)KeyEvent.Callback.onKeyMultiple(),當(dāng)按下視圖的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然后釋放時(shí)執(zhí)行,如果視圖可用且可點(diǎn)擊。
參數(shù)
keyCode-表示按鈕被按下的鍵碼,來(lái)自KeyEvent
event-定義了按鈕動(dòng)作的KeyEvent對(duì)象
返回值
如果你處理事件,返回true;如果你想下一個(gè)接收者處理事件,返回false。
當(dāng)內(nèi)存剩余較小且其它進(jìn)程請(qǐng)求較大內(nèi)存并需要立即分配,Android要回收某些進(jìn)程,進(jìn)程中的應(yīng)用程序組件會(huì)被銷(xiāo)毀。當(dāng)他們?cè)俅芜\(yùn)行時(shí),會(huì)重新開(kāi)始一個(gè)進(jìn)程。
當(dāng)決定終結(jié)哪個(gè)進(jìn)程時(shí),Android會(huì)權(quán)衡他們對(duì)用戶(hù)重要性的相對(duì)權(quán)值。例如,與運(yùn)行在屏幕可見(jiàn)的活動(dòng)進(jìn)程相比(前臺(tái)進(jìn)程),它更容易關(guān)閉一個(gè)進(jìn)程,它的活動(dòng)在屏幕是不可見(jiàn)(后臺(tái)進(jìn)程)。決定是否終結(jié)進(jìn)程,取決于運(yùn)行在進(jìn)程中的組件狀態(tài)。關(guān)于組件的狀態(tài),將在后面一篇——組件生命周期中介紹。
2、線(xiàn)程
雖然你可能會(huì)將你的應(yīng)用程序限制在一個(gè)進(jìn)程中,但有時(shí)候你會(huì)需要衍生一個(gè)線(xiàn)程做一些后臺(tái)工作。因?yàn)橛脩?hù)界面必須很快地響應(yīng)用戶(hù)的操作,所以活動(dòng)寄宿的線(xiàn)程不應(yīng)該做一些耗時(shí)的操作如網(wǎng)絡(luò)下載。任何不可能在短時(shí)間完成的操作應(yīng)該分配到別的線(xiàn)程。
線(xiàn)程在代碼中是用標(biāo)準(zhǔn)的Java線(xiàn)程對(duì)象創(chuàng)建的,Android提供了一些方便的類(lèi)來(lái)管理線(xiàn)程——Looper用于在線(xiàn)程中運(yùn)行消息循環(huán)、Handler用戶(hù)處理消息、HandlerThread用戶(hù)設(shè)置一個(gè)消息循環(huán)的線(xiàn)程。
Looper類(lèi)
該類(lèi)用戶(hù)在線(xiàn)程中運(yùn)行消息循環(huán)。線(xiàn)程默認(rèn)沒(méi)有消息循環(huán),可以在線(xiàn)程中調(diào)用prepare()創(chuàng)建一個(gè)運(yùn)行循環(huán);然后調(diào)用loop()處理消息直到循環(huán)結(jié)束。大部分消息循環(huán)交互是通過(guò)Handler類(lèi)。下面是一個(gè)典型的執(zhí)行一個(gè)Looper線(xiàn)程的例子,分別使用prepare()和loop()創(chuàng)建一個(gè)初始的Handler與Looper交互:
1. Android中進(jìn)程與進(jìn)程、線(xiàn)程與線(xiàn)程之間如何通信?
1)一個(gè) Android 程序開(kāi)始運(yùn)行時(shí),會(huì)單獨(dú)啟動(dòng)一個(gè)Process。
默認(rèn)情況下,所有這個(gè)程序中的Activity或者Service都會(huì)跑在這個(gè)Process。
默認(rèn)情況下,一個(gè)Android程序也只有一個(gè)Process,但一個(gè)Process下卻可以有許多個(gè)Thread。
2)一個(gè) Android 程序開(kāi)始運(yùn)行時(shí),就有一個(gè)主線(xiàn)程Main Thread被創(chuàng)建。該線(xiàn)程主要負(fù)責(zé)UI界面的顯示、更新和控件交互,所以又叫UI Thread。
3)一個(gè)Android程序創(chuàng)建之初,一個(gè)Process呈現(xiàn)的是單線(xiàn)程模型--即MainThread,所有的任務(wù)都在一個(gè)線(xiàn)程中運(yùn)行,所以,MainThread所調(diào)用的每一個(gè)函數(shù),其耗時(shí)應(yīng)該越短越好,而對(duì)于比較耗時(shí)的工作,應(yīng)該交給子線(xiàn)程去做,以避免主線(xiàn)程(UI線(xiàn)程)被阻塞,導(dǎo)致程序出現(xiàn)ANR(Application not response)
一個(gè)Activity就運(yùn)行在一個(gè)線(xiàn)程中嗎?或者編碼時(shí),如果不是明確安排在不同線(xiàn)程中的兩個(gè)Activity,其就都是在同一個(gè)線(xiàn)程中?那從一個(gè)Activity跳轉(zhuǎn)到另一個(gè)Activity時(shí),是不是跳出的那個(gè)Activity就處在睡眠狀態(tài)了?
【答】 每個(gè)Activity都有一個(gè)Process屬性,可以指定該Activity是屬于哪個(gè)進(jìn)程的。當(dāng)然如果不明確指明,應(yīng)該就是從屬于默認(rèn)進(jìn)程(Application指定的,如其未指定,應(yīng)該就是默認(rèn)主進(jìn)程)。
Android中有Task的概念,而同一個(gè)Task的各個(gè)Activity會(huì)形成一個(gè)棧,只有站定的Activity才有機(jī)會(huì)與用戶(hù)交互。
原文地址:Android中的進(jìn)程與線(xiàn)程 原文作者:江鵬
當(dāng)應(yīng)用程序的組件第一次運(yùn)行時(shí),Android將啟動(dòng)一個(gè)只有一個(gè)執(zhí)行線(xiàn)程的Linux進(jìn)程。默認(rèn),應(yīng)用程序所有的組件運(yùn)行在這個(gè)進(jìn)程和線(xiàn)程中。然而,你可以安排組件運(yùn)行在其他進(jìn)程中,且你可以為進(jìn)程衍生出其它線(xiàn)程。本文從下面幾點(diǎn)來(lái)介紹Android的進(jìn)程與線(xiàn)程:
1、進(jìn)程
組件運(yùn)行于哪個(gè)進(jìn)程中由清單文件控制。組件元素——<activity>、<service>、<receiver>、<provider>,都有一個(gè)process屬性可以指定組件運(yùn)行在哪個(gè)進(jìn)程中。這個(gè)屬性可以設(shè)置為每個(gè)組件運(yùn)行在自己的進(jìn)程中,或者某些組件共享一個(gè)進(jìn)程而其他的不共享。他們還可以設(shè)置為不同應(yīng)用程序的組件運(yùn)行在同一個(gè)進(jìn)程中——假設(shè)這些應(yīng)用程序共享同一個(gè)Linux用戶(hù)ID且被分配了同樣的權(quán)限。<application>元素也有process屬性,為所有的組件設(shè)置一個(gè)默認(rèn)值。
所有的組件都在特定進(jìn)程的主線(xiàn)程中實(shí)例化,且系統(tǒng)調(diào)用組件是由主線(xiàn)程派遣。不會(huì)為每個(gè)實(shí)例創(chuàng)建單獨(dú)的線(xiàn)程,因此,對(duì)應(yīng)這些調(diào)用的方法——諸如View.onKeyDown()報(bào)告用用戶(hù)的行為和生命周期通知,總是運(yùn)行在進(jìn)程的主線(xiàn)程中。這意味著,沒(méi)有組件當(dāng)被系統(tǒng)調(diào)用時(shí)應(yīng)該執(zhí)行很長(zhǎng)時(shí)間或阻塞操作(如網(wǎng)絡(luò)操作或循環(huán)計(jì)算),因?yàn)檫@將阻塞進(jìn)程中的其它組件。你可以為長(zhǎng)操作衍生獨(dú)立的線(xiàn)程。
public boolean onKeyDown(int keyCode,KeyEvent event):默認(rèn)實(shí)現(xiàn)KeyEvent.Callback.onKeyMultiple(),當(dāng)按下視圖的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然后釋放時(shí)執(zhí)行,如果視圖可用且可點(diǎn)擊。
參數(shù)
keyCode-表示按鈕被按下的鍵碼,來(lái)自KeyEvent
event-定義了按鈕動(dòng)作的KeyEvent對(duì)象
返回值
如果你處理事件,返回true;如果你想下一個(gè)接收者處理事件,返回false。
當(dāng)內(nèi)存剩余較小且其它進(jìn)程請(qǐng)求較大內(nèi)存并需要立即分配,Android要回收某些進(jìn)程,進(jìn)程中的應(yīng)用程序組件會(huì)被銷(xiāo)毀。當(dāng)他們?cè)俅芜\(yùn)行時(shí),會(huì)重新開(kāi)始一個(gè)進(jìn)程。
當(dāng)決定終結(jié)哪個(gè)進(jìn)程時(shí),Android會(huì)權(quán)衡他們對(duì)用戶(hù)重要性的相對(duì)權(quán)值。例如,與運(yùn)行在屏幕可見(jiàn)的活動(dòng)進(jìn)程相比(前臺(tái)進(jìn)程),它更容易關(guān)閉一個(gè)進(jìn)程,它的活動(dòng)在屏幕是不可見(jiàn)(后臺(tái)進(jìn)程)。決定是否終結(jié)進(jìn)程,取決于運(yùn)行在進(jìn)程中的組件狀態(tài)。關(guān)于組件的狀態(tài),將在后面一篇——組件生命周期中介紹。
2、線(xiàn)程
雖然你可能會(huì)將你的應(yīng)用程序限制在一個(gè)進(jìn)程中,但有時(shí)候你會(huì)需要衍生一個(gè)線(xiàn)程做一些后臺(tái)工作。因?yàn)橛脩?hù)界面必須很快地響應(yīng)用戶(hù)的操作,所以活動(dòng)寄宿的線(xiàn)程不應(yīng)該做一些耗時(shí)的操作如網(wǎng)絡(luò)下載。任何不可能在短時(shí)間完成的操作應(yīng)該分配到別的線(xiàn)程。
線(xiàn)程在代碼中是用標(biāo)準(zhǔn)的Java線(xiàn)程對(duì)象創(chuàng)建的,Android提供了一些方便的類(lèi)來(lái)管理線(xiàn)程——Looper用于在線(xiàn)程中運(yùn)行消息循環(huán)、Handler用戶(hù)處理消息、HandlerThread用戶(hù)設(shè)置一個(gè)消息循環(huán)的線(xiàn)程。
Looper類(lèi)
該類(lèi)用戶(hù)在線(xiàn)程中運(yùn)行消息循環(huán)。線(xiàn)程默認(rèn)沒(méi)有消息循環(huán),可以在線(xiàn)程中調(diào)用prepare()創(chuàng)建一個(gè)運(yùn)行循環(huán);然后調(diào)用loop()處理消息直到循環(huán)結(jié)束。大部分消息循環(huán)交互是通過(guò)Handler類(lèi)。下面是一個(gè)典型的執(zhí)行一個(gè)Looper線(xiàn)程的例子,分別使用prepare()和loop()創(chuàng)建一個(gè)初始的Handler與Looper交互:
2.1、遠(yuǎn)程過(guò)程調(diào)用(Remote procedure calls,RPCs)
Android有一個(gè)輕量級(jí)的遠(yuǎn)程過(guò)程調(diào)用機(jī)制——方法在本地調(diào)用卻在遠(yuǎn)程(另外一個(gè)進(jìn)程中)執(zhí)行,結(jié)果返回給調(diào)用者。這需要將方法調(diào)用和它伴隨的數(shù)據(jù)分解為操作系統(tǒng)能夠理解的層次,從本地進(jìn)程和地址空間傳輸?shù)竭h(yuǎn)程進(jìn)程和地址空間,并重新組裝調(diào)用。返回值以相反方向傳輸。Android提供了做這些工作的所有代碼,這樣我們可以專(zhuān)注于定義和執(zhí)行RPC接口本身。
一個(gè)RPC接口僅包含方法。所有的方法同步地執(zhí)行(本地方法阻塞直到遠(yuǎn)程方法執(zhí)行完成),即使是沒(méi)有返回值。簡(jiǎn)言之,該機(jī)制工作原理如下:首先,你用簡(jiǎn)單的IDL(interface definition language,接口定義語(yǔ)言)聲明一個(gè)你想實(shí)現(xiàn)的RPC接口。從這個(gè)聲明中,aidl工具生成一個(gè)Java接口定義,提供給本地和遠(yuǎn)程進(jìn)程。它包含兩個(gè)內(nèi)部類(lèi),如下圖所示:
內(nèi)部類(lèi)有管理你用IDL定義的接口的遠(yuǎn)程過(guò)程調(diào)用所需要的所有代碼。這兩個(gè)內(nèi)部類(lèi)都實(shí)現(xiàn)了IBinder接口。其中之一就是在本地由系統(tǒng)內(nèi)部使用,你寫(xiě)代碼可以忽略它。另外一個(gè)是Stub,擴(kuò)展自Binder類(lèi)。除了用于有效地IPC(interprocess communication)調(diào)用的內(nèi)部代碼,內(nèi)部類(lèi)在RPC接口聲明中還包含方法聲明。你可以定義Stub的子類(lèi)實(shí)現(xiàn)這些方法,如圖中所示。
通常情況下,遠(yuǎn)程過(guò)程有一個(gè)服務(wù)管理(因?yàn)榉?wù)能通知系統(tǒng)關(guān)于進(jìn)程和它連接的其它進(jìn)程的信息)。它有由aidl工具生成的接口文件和Stub子類(lèi)實(shí)現(xiàn)的RPC方法。服務(wù)的客戶(hù)端僅有由aidl工具生成的接口文件。
下面介紹服務(wù)如何與它的客戶(hù)端建立連接:
· 服務(wù)的客戶(hù)端(在本地端的)應(yīng)該實(shí)現(xiàn)onServiceConnected() 和onServiceDisconnected() 方法,因此當(dāng)與遠(yuǎn)程服務(wù)建立連接成功和斷開(kāi)連接是會(huì)通知它。然后調(diào)用bindService() 建立連接。
· 服務(wù)的onBind()方法將實(shí)現(xiàn)為接受或拒絕連接,者取決于它接受到的意圖(該意圖傳送到binServive())。如果連接被接受,它返回一個(gè)Stub子類(lèi)的實(shí)例。
· 如果服務(wù)接受連接,Android調(diào)用客戶(hù)端的onServiceConnected()方法且傳遞給它一個(gè)IBinder對(duì)象,返回由服務(wù)管理的Stub子類(lèi)的一個(gè)代理。通過(guò)代理,客戶(hù)端可以調(diào)用遠(yuǎn)程服務(wù)。
這里只是簡(jiǎn)單地描述,省略了一些RPC機(jī)制的細(xì)節(jié)。你可以查閱相關(guān)資料或繼續(xù)關(guān)注Android開(kāi)發(fā)之旅,后面將為你奉上。
2.2、線(xiàn)程安全方法
在一些情況下,你實(shí)現(xiàn)的方法可能會(huì)被不止一個(gè)線(xiàn)程調(diào)用,因此必須寫(xiě)成線(xiàn)程安全的。這對(duì)遠(yuǎn)程調(diào)用方法是正確的——如上一節(jié)討論的RPC機(jī)制。當(dāng)從IBinder進(jìn)程中調(diào)用一個(gè)IBinder對(duì)象中實(shí)現(xiàn)的一個(gè)方法,這個(gè)方法在調(diào)用者的線(xiàn)程中執(zhí)行。然而,當(dāng)從別的進(jìn)程中調(diào)用,方法將在Android維護(hù)的IBinder進(jìn)程中的線(xiàn)程池中選擇一個(gè)執(zhí)行,它不在進(jìn)程的主線(xiàn)程中執(zhí)行。例如,一個(gè)服務(wù)的onBind()方法在服務(wù)進(jìn)程的主線(xiàn)程中被調(diào)用,在onBind()返回的對(duì)象中執(zhí)行的方法(例如,實(shí)現(xiàn)RPC方法的Stub子類(lèi))將在線(xiàn)程池中被調(diào)用。由于服務(wù)可以有一個(gè)以上的客戶(hù)端,所以同時(shí)可以有一個(gè)以上的線(xiàn)程在執(zhí)行同一個(gè)IBinder方法。因此,IBinder的方法必須是線(xiàn)程安全的。
同樣,一個(gè)內(nèi)容提供者可以接受其它進(jìn)程產(chǎn)生的數(shù)據(jù)請(qǐng)求。雖然ContentResolver 和 ContentProvider 類(lèi)隱藏進(jìn)程通信如何管理的,對(duì)應(yīng)哪些請(qǐng)求的ContentResolver 方法——query()、insert()、delete()、update()、getType(),在內(nèi)容提供者的進(jìn)程的線(xiàn)程池中被調(diào)用,而不是在這一進(jìn)程的主線(xiàn)程中。因?yàn)檫@些方法可以同時(shí)從任意數(shù)量的線(xiàn)程中調(diào)用,他們也必須實(shí)現(xiàn)為線(xiàn)程安全的。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。