處理程序和執行緒總覽

應用程式元件啟動,且應用程式不具任何其他元件時 Android 系統透過單一執行緒 根據預設,同一個應用程式的所有元件都會在同一個程序和執行緒中執行。 main 執行緒

如果應用程式元件啟動,且已有處理程序 因為應用程式中的另一個元件已啟動,所以 並使用相同的執行執行緒。不過,您可以安排 應用程式中的不同元件,以便在各自的程序中執行 適用於任何程序的執行緒。

本文件說明程序和執行緒在 Android 應用程式中的運作方式。

處理程序

根據預設,應用程式的所有元件都會在相同的程序中執行,大多數應用程式 請勿加以變更不過,如果您需要控制特定程序 請在資訊清單檔案中進行這項操作。

每種元件元素 (<activity><service><receiver><provider>) 的資訊清單項目都支援可指定android:process 並在元件執行時處理元件您可以設定這項屬性,讓每個元件都能執行 或讓某些元件共用程序,其他元件則不會。

您也可以設定 android:process 讓不同應用程式元件在相同的 Google 應用程式中執行 處理程序,前提是應用程式共用相同的 Linux 使用者 ID,且使用 相同憑證

<application> 元素也支援 android:process 屬性,可用於設定 則適用於所有元件的預設值。

Android 可能會在資源不多時關閉程序 其他流程要求 使用者會立即提供服務適用範圍 元件會在關閉程序中執行的元件遭到刪除。已開始程序 都會產生同樣的效果

在決定要關閉哪些程序時,Android 系統會從 使用者。例如,更容易關閉不再存在的程序代管活動 對比代管可見活動的程序。決定是否使用 因此,會依該程序中執行的元件狀態而定。

如要進一步瞭解程序生命週期,以及程序與應用程式狀態之間的關係,請參閱 處理程序和應用程式生命週期

執行緒

應用程式啟動時,系統會為應用程式建立執行作業執行緒, 主執行緒這個執行緒十分重要,因為這個執行緒會負責將事件分派給 適用的使用者介面小工具,包括繪圖事件。這個 幾乎一定是應用程式與元件互動的執行緒 前往 Android UI 工具包的 android.widgetandroid.view 個套件。 因此,主要執行緒有時會 UI 執行緒不過在特殊情況下 可能不是其 UI 執行緒。詳情請參閱「Thread 」 註解

系統「不會」為元件的每個執行個體分別建立執行緒。所有語言 如果是在同一程序中執行的元件,就會在 UI 執行緒中執行個體化,而對 再從該執行緒分派每個元件因此回應系統的方法 回呼,例如 onKeyDown() 回報使用者動作或生命週期回呼方法 - 一律在程序的 UI 執行緒中執行。

舉例來說,當使用者輕觸畫面上的按鈕時,應用程式的 UI 執行緒就會分派 小工具會收到觸控事件,進而設定了已按下的狀態,並對 事件佇列。UI 執行緒會將要求移出佇列,並通知小工具重新繪製 機器學習是向機器提供資料和答案 讓機器自行探索規則的科學

除非您正確實作應用程式,否則這個單一執行緒模型 應用程式如果為了回應使用者互動而執行大量作業,可能會導致效能不佳。 在 UI 執行緒中執行長時間作業,例如網路存取或 資料庫查詢,會封鎖整個 UI。執行緒遭到封鎖後,系統就無法分派任何事件, 包括繪圖事件

從使用者的角度來看 應用程式似乎停止運作。更糟的是,如果 UI 執行緒遭到封鎖數秒以上, 使用者會看到「應用程式 回應」(ANR) 對話方塊。使用者接著可能會決定退出應用程式,甚至解除安裝應用程式 基礎架構

請注意,Android UI 工具包「並非」執行緒安全。因此請勿操縱 建構出 UI透過 UI 對使用者介面進行所有操作 。Android 單一執行緒模型有兩項規則:

  1. 請勿封鎖 UI 執行緒。
  2. 請勿從 UI 執行緒外部存取 Android UI 工具包。

工作站執行緒

鑒於這種單一執行緒模型,主要執行緒回應速度的關鍵在於 的使用者介面。如果您有需要執行的作業 不需要同步,請務必在個別的背景worker 執行緒。不過請注意,除了 UI 或主執行緒

為協助您遵守這些規則,Android 提供了透過其他方式存取 UI 執行緒的方式。 。以下列舉幾項適用的方法:

以下範例使用 View.post(Runnable)

Kotlin

fun onClick(v: View) {
    Thread(Runnable {
        // A potentially time consuming task.
        val bitmap = processBitMap("image.png")
        imageView.post {
            imageView.setImageBitmap(bitmap)
        }
    }).start()
}

Java

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            // A potentially time consuming task.
            final Bitmap bitmap =
                    processBitMap("image.png");
            imageView.post(new Runnable() {
                public void run() {
                    imageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

這項實作具有執行緒安全的執行緒,因為背景作業是從另一個執行緒完成 ImageView 一律會透過 UI 執行緒進行操作。

不過,隨著作業複雜度增加,這類程式碼也可能變得越來越複雜 難以維護如要處理與背景工作執行緒更複雜的互動,您可以考慮 在背景工作執行緒中使用 Handler 處理 UI 執行緒傳送的訊息。如需完整說明 安排背景執行緒工作並回覆 UI 執行緒,請參閱 背景工作總覽

執行緒安全方法

在某些情況下,您實作的方法會從多個執行緒呼叫,且 因此都必須以執行緒安全的方式編寫。

這主要適用於可從遠端呼叫的方法,例如繫結服務中的方法。如果使用 IBinder 中實作的方法與 IBinder 正在執行,此方法會在呼叫端的執行緒中執行。 不過,當呼叫源自另一個程序時,該方法會在選擇的執行緒中執行 系統在與 IBinder 相同的程序中維護的執行緒集區。 而不是在程序的 UI 執行緒中執行。

例如服務 系統會從應用程式的 UI 執行緒呼叫 onBind() 方法, 服務程序、在 onBind() 傳回的物件中實作的方法,例如 實作遠端程序呼叫 (RPC) 方法的子類別是從執行緒呼叫 集區中由於一項服務可以有多個用戶端,因此多個集區執行緒可以 並使用相同的 IBinder 方法,因此 IBinder 方法必須 確保執行緒安全

同樣地,內容供應器可以接收源自其他程序的資料要求。 《ContentResolver》和《ContentProvider》 類別隱藏了管理處理序間通訊 (IPC) 的細節, 但回應這些要求的 ContentProvider 方法 query(), insert(), delete(), update(), 和 getType()—為 內容供應器程序的執行緒集區呼叫,而非 UI 處理資料的執行緒這些方法可能會從 所以必須一併實作,以確保執行緒安全。

處理序間通訊

Android 提供使用遠端程序呼叫 (RPC) 的 IPC 機制,其中活動或其他應用程式會呼叫方法 但在另一個程序遠端執行,並將任何結果傳回給 呼叫。您需要將方法呼叫及其資料分解為作業系統能使用的層級 從本機處理程序和位址空間傳輸至遠端處理程序並 內部位址空間,再重新組裝並重演

傳回值如下: 反向傳輸。Android 會提供執行這些 IPC 的所有程式碼 交易,因此可專注於定義和實作遠端程序呼叫 (RPC) 程式設計介面。

若要執行 IPC,應用程式必須使用 bindService() 繫結至服務。詳情請參閱服務總覽