Android程式與執行緒

文藝小青年發表於2017-04-01

當某個元件第一次執行的時候,Android啟動了一個程式。預設的,所有的元件和程式執行在這個程式和執行緒中。

也可以安排元件在其他的程式或者執行緒中執行

程式

元件執行的程式由manifest file控制。元件的節點 — <activity>, <service>, <receiver>, 和 <provider> — 都包含一個 process 屬性。這個屬性可以設定元件執行的程式:可以配置元件在一個獨立程式執行,或者多個元件在同一個程式執行。甚至可以多個程式在一個程式中執行——如果這些程式共享一個User ID並給定同樣的許可權。<application> 節點也包含 process 屬性,用來設定程式中所有元件的預設程式。

所有的元件在此程式的主執行緒中例項化,系統對這些元件的呼叫從主執行緒中分離。並非每個物件都會從主執行緒中分離。一般來說,響應例如View.onKeyDown()使用者操作的方法和通知的方法也在主執行緒中執行。這就表示,元件被系統呼叫的時候不應該長時間執行或者阻塞操作(如網路操作或者計算大量資料),因為這樣會阻塞程式中的其他元件。可以把這類操作從主執行緒中分離。

當更加常用的程式無法獲取足夠記憶體,Android可能會關閉不常用的程式。下次啟動程式的時候會重新啟動程式。

當決定哪個程式需要被關閉的時候, Android會考慮哪個對使用者更加有用。如Android會傾向於關閉一個長期不顯示在介面的程式來支援一個經常顯示在介面的程式。是否關閉一個程式決定於元件在程式中的狀態,參見後面的章節Component Lifecycles.

執行緒

即使為元件分配了不同的程式,有時候也需要再分配執行緒。比如使用者介面需要很快對使用者進行響應,因此某些費時的操作,如網路連線、下載或者非常佔用伺服器時間的操作應該放到其他執行緒。

執行緒通過java的標準物件Thread 建立. Android 提供了很多方便的管理執行緒的方法:— Looper 線上程中執行一個訊息迴圈; Handler 傳遞一個訊息; HandlerThread 建立一個帶有訊息迴圈的執行緒。

遠端呼叫Remote procedure calls

Android有一個遠端呼叫(RPCs) 的輕量級機制— 通過這個機制,方法可以在本地呼叫,在遠端執行(在其他程式執行),還可以返回一個值。要實現這個需求,必須分解方法呼叫,並且所有要傳遞的資料必須是作業系統可以訪問的級別。從本地的程式和記憶體地址傳送到遠端的程式和記憶體地址並在遠端處理和返回。返回值必須向相反的方向傳遞。Android提供了做以上操作的程式碼,所以開發者可以專注於實現RPC的介面。

一個RPC介面只能包含方法。所有的方法都是同步執行的(直到遠端方法返回,本地方法才結束阻塞),沒有返回值的時候也是如此。

簡單來說,這個機制是這樣的:使用IDL (interface definition language)定義你想要實現的介面, aidl 工具可以生成用於java的介面定義,本地和遠端都要使用這個定義。它包含2個類,見下圖:

binder_rpc

inner類包含了所有的管理遠端程式(符合IDL描述的介面)所需要的程式碼。所有的inner類實現了IBinder 介面.其中一個在本地使用,可以不管它的程式碼;另外一個叫做Stub繼承了 Binder 類。為了實現遠端呼叫,這個類包含RPC介面。開發者可以繼承Stub類來實現需要的方法

一般來說,遠端程式會被一個service管理(因為service可以通知作業系統這個程式的資訊並和其他程式通訊),它也會包含aidl 工具產生的介面檔案,Stub類實現了遠處那個方法。服務的客戶端只需要aidl 工具產生的介面檔案。

以下是如何連線服務和客戶端呼叫:

  • ·服務的客戶端(本地)會實現onServiceConnected() 和onServiceDisconnected() 方法,這樣,當客戶端連線或者斷開連線的時候可以獲取到通知。通過 bindService() 獲取到服務的連線。
  • · 服務的 onBind() 方法中可以接收或者拒絕連線,取決它收到的intent (intent通過 bindService()方法連線到服務). 如果服務接收了連線,會返回一個Stub類的例項.
  • · 如果服務接受了連線,Android會呼叫客戶端的onServiceConnected() 方法,並傳遞一個Ibinder物件(系統管理的Stub類的代理),通過這個代理,客戶端可以連線遠端的服務。

以上的描述省略很多RPC的機制。請參見Designing a Remote Interface Using AIDL 和 IBinder 類。

執行緒安全的方法

在某些情況下,方法可能呼叫不止一個的執行緒,因此需要注意方法的執行緒安全。

對於可以遠端呼叫的方法,也要注意這點。當一個呼叫在Ibinder物件中的方法的程式啟動了和Ibinder物件相同的程式,方法就在Ibinder的程式中執行。但是,如果呼叫者發起另外一個程式,方法在另外一個執行緒中執行,這個執行緒在和IBinder物件在一個執行緒池中;它不會在程式的主執行緒中執行。例如,一個service從主執行緒被呼叫onBind() 方法,onBind() 返回的物件(如實現了RPC的Stub子類)中的方法會被從執行緒池中呼叫。因為一個服務可能有多個客戶端請求,不止一個執行緒池會在同一時間呼叫IBinder的方法。因此IBinder必須執行緒安全。

簡單來說,一個content provider 可以接收其他程式的資料請求。即使ContentResolver和ContentProvider類沒有隱藏了管理互動的細節,ContentProvider中響應這些請求的方法(query(), insert(), delete(), update(), and getType() )— 是在content provider的執行緒池中被呼叫的,而不是ContentProvider的本身程式。因為這些方法可能是同時從很多執行緒池執行的,所以這些方法必須要執行緒安全。

本文轉自feisky部落格園部落格,原文連結:http://www.cnblogs.com/feisky/archive/2010/01/01/1637409.html,如需轉載請自行聯絡原作者


相關文章