活動簡介

Activity 類別是 Android 應用程式的重要元件,而活動的啟動和組合方式,則是平台應用程式模型的基本部分。與使用 main 方法啟動應用程式的程式設計範例不同,Android 系統會叫用與生命週期特定階段相對應的特定回呼方法,在 Activity 執行個體中啟動程式碼。

本文將介紹活動的概念,並提供一些輕量級的指南,說明如何使用活動。如要進一步瞭解應用程式架構的最佳做法,請參閱「應用程式架構指南」。

活動的概念

行動應用程式體驗與電腦版不同,使用者與應用程式的互動不一定會從相同位置開始。相反地,使用者歷程通常會以非決定性的方式開始。舉例來說,如果從主畫面開啟電子郵件應用程式,可能會看到電子郵件清單。相反地,如果您使用社群媒體應用程式啟動電子郵件應用程式,可能會直接進入電子郵件應用程式的電子郵件撰寫畫面。

Activity 類別的設計宗旨,就是為了簡化這個範例。當一個應用程式叫用另一個應用程式時,呼叫應用程式會叫用另一個應用程式中的活動,而不是將該應用程式視為不可分割的整體。因此,活動是應用程式與使用者互動的進入點。您要將活動實作為 Activity 類別的子類別。

活動會提供應用程式繪製 UI 的視窗。這個視窗通常會填滿整個螢幕,但可能比螢幕小,並浮動在其他視窗上方。

一般來說,應用程式中的一項活動會指定為「主要活動」,也就是使用者啟動應用程式時顯示的第一個畫面。在現代的 Compose 應用程式中,這是唯一必要的活動,因為它會在單一活動架構中代管可組合項,而不是擁有檢視區塊階層。應用程式不會為畫面提供多個活動,而是活動中的可組合項會代管多個導覽目的地。

如要在應用程式中使用活動,必須在應用程式資訊清單中註冊活動相關資訊,並瞭解活動生命週期。本文件其餘部分將介紹這些主題。

設定資訊清單

如要讓應用程式使用活動,您必須在資訊清單中宣告活動和特定屬性。

宣告活動

如要宣告活動,請開啟資訊清單檔案,並將 <activity> 元素新增為 <application> 元素的子項。例如:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

這個元素唯一需要的屬性是 android:name,可指定活動的類別名稱。您也可以新增屬性,定義活動特徵,例如標籤、圖示或 UI 主題。如要進一步瞭解這些和其他屬性,請參閱 <activity> 元素參考文件。

宣告意圖篩選器

意圖篩選器是 Android 平台非常強大的功能。不僅能根據明確要求啟動活動,也能根據隱含要求啟動活動。舉例來說,明確要求可能會指示系統「在 Gmail 應用程式中啟動『傳送電子郵件』活動」。相反地,隱含要求會告知系統「在任何可執行這項工作的活動中,啟動『傳送電子郵件』畫面」。當系統 UI 詢問使用者要使用哪個應用程式執行工作時,就是意圖篩選器在運作。

如要使用這項功能,請在 <activity> 元素中宣告 <intent-filter> 屬性。這個元素的定義包含 <action> 元素,以及視需要包含的 <category> 元素和/或 <data> 元素。這些元素會合併指定活動可回應的意圖類型。舉例來說,下列程式碼片段說明如何設定 Activity,傳送文字資料和電子郵件,並接收其他 Activity 的要求來執行這項操作:

<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
   <intent-filter>
        <action android:name="android.intent.action.SENDTO" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="mailto" />
    </intent-filter>
</activity>

在本範例中,<action> 元素指定這項活動會傳送資料。將 <category> 元素宣告為 DEFAULT,即可讓活動接收啟動要求。<data> 元素會指定這項活動可傳送的資料類型。下列程式碼片段說明如何呼叫上述活動來撰寫電子郵件:

fun composeEmail(addresses: Array<String>, subject: String) {
    val intent = Intent(Intent.ACTION_SENDTO).apply {
        data = Uri.parse("mailto:") // Only email apps handle this.
        putExtra(Intent.EXTRA_EMAIL, addresses)
        putExtra(Intent.EXTRA_SUBJECT, subject)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

如果您希望應用程式獨立運作,且不允許其他應用程式啟動其活動,則不需要任何其他意圖篩選器。如果不想讓其他應用程式使用某些活動,請不要為這些活動設定意圖篩選器,並使用明確意圖自行啟動。如要進一步瞭解活動如何回應意圖,請參閱「意圖和意圖篩選器」。

處理傳入的意圖

以下範例顯示管理活動生命週期的模式,同時處理多種意圖類型:單一文字分享、單一圖片和多個圖片陣列。透過集中式 handleIntent 函式傳送這些不同的輸入內容,可確保 ACTION_SENDACTION_SEND_MULTIPLE 動作都能正確剖析,並委派給 ViewModel,以更新反應式 UI。

class ExampleActivity : ComponentActivity() {
  private val viewModel: MyViewModel by viewModels()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    handleIntent(intent)
    setContent {
      ComposeApp(viewModel)
    }
  }

  override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    handleIntent(intent)
  }

  private fun handleIntent(intent: Intent?) {
    when (intent?.action) {
      Intent.ACTION_SEND -> {
        if ("text/plain" == intent.type) {
          intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
            viewModel.handleText(it) // Update UI to reflect text being shared
          }
        } else if (intent.type?.startsWith("image/") == true) {
          (intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java))?.let {
            viewModel.handleImage(it) // Update UI to reflect image being shared
          }
        }
      }

      Intent.ACTION_SEND_MULTIPLE -> {
          if (intent.type?.startsWith("image/") == true) {
              intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)?.let {
                  viewModel.handleMultipleImages(it) // Update UI to reflect multiple images being shared
              }
          } else {
              // Handle other types
          }
      }

      else -> {
          // Handle other intents
      }
    }
  }
}

宣告權限

您可以使用資訊清單的 <activity> 標記,控管哪些應用程式可以啟動特定活動。除非父項活動和子項活動在資訊清單中具有相同的權限,否則父項活動無法啟動子項活動。如果為上層活動宣告 <uses-permission> 元素,每個子項活動都必須有相符的 <uses-permission> 元素。

舉例來說,如果應用程式想使用名為 SocialApp 的假設應用程式,在社群媒體上分享貼文,SocialApp 本身必須定義呼叫應用程式必須具備的權限:

<manifest>
<activity android:name="...."
   android:permission="com.google.socialapp.permission.SHARE_POST"

/>

接著,如要允許應用程式呼叫 SocialApp,應用程式必須符合 SocialApp 資訊清單中設定的權限集:

<manifest>
   <uses-permission android:name="com.google.socialapp.permission.SHARE_POST" />
</manifest>

如要進一步瞭解權限和一般安全性,請參閱安全性檢查清單

管理活動生命週期

在生命週期中,活動會經歷多種狀態。您可以使用一系列回呼來處理狀態之間的轉換。下列各節將介紹這些回呼。在 Compose 應用程式中,不建議直接連結這些回呼。請改用 Lifecycle API 觀察狀態變化。詳情請參閱「整合生命週期與 Compose」。

onCreate

您必須實作這個回呼,系統會在建立活動時觸發這個回呼。實作時,請初始化活動的重要元件。舉例來說,應用程式應在此處建立檢視區塊,並將資料繫結至清單。

在 Compose 應用程式中,使用這個回呼透過 setContent 設定主機可組合函式,如下所示:

class MyActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text(text = stringResource(id = R.string.greeting))
        }
    }
}

onCreate 完成後,下一個回呼一律為 onStart

onStart

onCreate 結束時,活動會進入「已啟動」狀態,使用者也會看到活動。這個回呼包含活動的最終準備工作,即將移至前景並成為互動式活動。

onResume

系統會在活動開始與使用者互動前,呼叫這個回呼。此時,活動位於活動堆疊頂端,並會擷取所有使用者輸入內容。應用程式的大部分核心功能都是在 onResume 方法中實作。

onPause 回呼一律會接在 onResume 之後。

onPause

當活動失去焦點並進入「已暫停」狀態時,系統會呼叫 onPause。舉例來說,使用者輕觸「返回」或「最近使用的應用程式」按鈕時,就會進入這個狀態。當系統為您的活動呼叫 onPause 時,技術上來說,您的活動仍會部分顯示,但通常表示使用者即將離開活動,且活動很快就會進入「已停止」或「已恢復」狀態。

如果使用者希望 UI 更新,處於「已暫停」狀態的活動可能會繼續更新 UI。例如顯示導航地圖畫面或播放媒體的活動。即使這類活動失去焦點,使用者也預期 UI 會持續更新。

不應使用 onPause 儲存應用程式或使用者資料、發出網路呼叫,或執行資料庫交易。如要瞭解如何儲存資料,請參閱「儲存及還原暫時性 UI 狀態」。

onPause 執行完畢後,下一個回呼是 onStoponResume,取決於活動進入「已暫停」狀態後發生的情況。

onStop

當活動不再對使用者顯示時,系統會呼叫 onStop。這可能是因為活動遭到刪除、新活動正在啟動,或是現有活動進入「已恢復」狀態,並涵蓋已停止的活動。在上述所有情況下,停止的活動都不會再顯示。

如果活動要返回與使用者互動,系統下一個呼叫的回呼是 onRestart;如果活動要完全終止,系統下一個呼叫的回呼是 onDestroy

onRestart

當處於「已停止」狀態的活動即將重新啟動時,系統會叫用這個回呼。onRestart 會還原活動停止時的狀態。

這個回呼一律會接在 onStart 之後。

onDestroy

系統會在活動遭到刪除前,叫用這個回呼。

這是活動收到的最後一個回呼。onDestroy 通常會實作,確保活動或包含活動的程序遭到刪除時,所有活動資源都會釋出。

本節僅簡要介紹這個主題。如要進一步瞭解活動生命週期及其回呼,請參閱「活動生命週期」一文。