1.1.1 啟用組件:Intent
當接收到ContentResolver發出的請求後,內容提供者被啟用。而其它三種組件──活動(Activity)、服務和廣播接收器被一種叫做Intent的非同步資訊所啟用。Intent是一個儲存著資訊內容的Intent對象。對於Activity和服務來說,它指明了請求的操作名稱以及作為操作對象的資料URI和其它一些資訊。比如說,它可以為Activity傳遞一個請求向使用者顯示一張圖片,或者讓使用者編輯一些文本。而對於廣播接收器而言,Intent對象則指明了通知的行為。比如,它可以通知所有感興趣的對象照相按鈕被按下。
啟用不同類型的組件的方法是不同的:
- 傳遞一個Intent對象至Context.startActivity()或Activity.startActivityForResult()啟動(或其他假定的新任務)一個Activity。相應的Activity可以通過調用getIntent()方法來查看啟用它的Intent對象。Android通過調用Activity的onNewIntent()方法來向Activity傳遞新的Intent。
Activity通常啟動其他的Activity。如果它期望它所啟動的那個Activity返回一個結果,會調用startActivityForResult()來取代startActivity()。比如說,如果啟動了另外一個Activity以使使用者挑選一張照片,它應該希望返回被選中的照片。結果將會被封裝在一個Intent對象中,並傳遞給啟動Activity的onActivityResult()方法。
- 通過傳遞一個Intent對象至Context.startService()將啟動一個服務(或給予正在啟動並執行服務一個新的指令)。Android調用服務的onStart()方法並將Intent對象傳遞給它。
與此類似,Intent可以被組件傳遞給Context.bindService()以建立與一個正在啟動並執行目標服務的串連。服務通過其onBind()方法擷取這個Intent對象(如果服務尚未啟動,bindService()會先啟動它)。比如,一個Activity可以串連至上述的音樂回放服務,並提供給使用者一個可操作的(使用者介面)以對回放進行控制。這個Activity可以調用bindService()來建立串連,然後調用服務定義的對象來控制回放。後面一節:遠程方法調用將更詳細的闡明如何綁定至服務。
- 應用程式可以將Intent對象傳遞給Context.sendBroadcast()、Context.sendOrderedBroadcast()和Context.sendStickyBroadcast()方法、以及他們的任何變種形式來產生一個廣播。Android會調用所有對此廣播有興趣的廣播接收器的onReceive()方法,並將Intent傳遞給它們。
欲瞭解更多Intent訊息的資訊,請參閱章節Intent和Intent Filter(濾過器)。
1.1.2 關閉組件
內容提供者僅在響應來自ContentResolver的請求時啟用。而廣播接收器僅在響應廣播訊息的時候啟用。所以,沒有必要顯式的關閉這些組件。
而Activity則不同,它提供了使用者介面。並與使用者進行會話。所以只要會話依然持續,哪怕會話過程暫時停頓,它都會一直保持啟用狀態。與此相似,服務也會在很長一段時間內保持運行。所以Android為關閉Activity和服務提供了一系列的方法。
- 可以通過finish()方法來關閉一個Activity。Activity可以通過調用另外一個Activity(它通過startActivityForResult()啟動)的finishActivity()方法來關閉它。
- 服務可以通過調用它的stopSelf()方法來停止,或者調用Context.stopService()。
系統也會在組件不再被使用的時候或者Android需要為活動組件提供更多記憶體的時候關閉它。後面組件的生命週期一節,將對這種情況進行更詳細的討論。
1.1.3 manifest檔案
當Android啟動一個應用程式組件之前,它必須知道那個組件是存在的。所以,應用程式會在一個manifest檔案中聲明它的組件,這個檔案被打包到Android包中。這個.apk檔案還將包括應用程式的代碼、檔案以及其它資源。
這個manifest檔案以XML作為結構格式,所有Android應用程式都叫AndroidManifest.xml。除了聲明應用程式組件, 它還提供很多額外功能,比如指明應用程式所需連結的庫名稱(除了預設的Android庫之外)以及聲明應用程式期望獲得的各種許可權。
但manifest檔案的主要功能仍然是向Android聲明應用程式的組件。例如,Activity可以這樣聲明:
<?xml version=”1.0” encoding=”utf-8”?>
<manifest . . . >
<application . . . >
<activity android:name=”com.example.project.FreneticActivity”
android:icon=”@drawable/small_pic.png”
android:label=”@string/freneticLabel”
. . . >
</activity>
. . .
</application>
</manifest>
<activity>元素的name屬性指定了實現了這個Activity的 Activity子類。Icon和label屬性指向了展示給使用者的此Activity的表徵圖和標籤資源檔。
其它組件也以類似的方法聲明——<service>元素用於聲明服務,<receiver>元素用於聲明廣播接收器,而<provider>元素用於聲明內容提供者。Manifest檔案中未進行聲明的Activity、服務以及內容提供者將不為系統所見,從而也就不會被運行。然而,廣播接收器既可以在manifest檔案中聲明,也可以在代碼中進行動態建立,並以調用Context.registerReceiver()方式註冊至系統。
欲更多瞭解如何為應用程式構建manifest檔案,請參閱AndroidManifest.xml檔案一節。
1.1.4 Intent Filter(過濾器)
Intent對象可以顯式指定目標組件。如果指定目標組件,Android會找到這個組件(根據manifest檔案中的聲明)並啟用它。但如果Intent沒有指定目標組件,Android就必須找到最合適的組件來響應Intent。這個過程是通過比較Intent對象和所有潛在目標對象的Intent Filter實現。組件的Intent Filter會通知Android它所能處理的Intent類型。和組件的其他重要訊息一樣,Intent Filter也是在manifest檔案聲明。下面是上面樣本的一個擴充,向Activity添加了兩個Intent Filter聲明:
<?xml version=”1.0” encoding=”utf-8”?>
<manifest . . . >
<application . . . >
<activity android:name=”com.example.project.FreneticActivity”
android:icon=”@drawable/small_pic.png”
android:label=”@string/freneticLabel”
. . . >
<intent-filter . . . >
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
<intent-filter . . . >
<action android:name=”com.example.project.BOUNCE” />
<data android:type=”image/jpeg” />
<category android:name=”android.intent.category.DEFAULT” />
</intent-filter>
</activity>
. . .
</application>
</manifest>
樣本中的第一個過濾器——行為“android.intent.action.MAIN”和類別“android.intent.category.LAUNCHER”的組合最常見的。它標明這個Activity將在應用程式啟動項中顯示,即使用者在裝置上看到的可以啟動的應用程式列表。換句話說,這個Activity是應用程式的入口,是使用者選擇該應用程式後所看到的第一個Activity。
第二個過濾器聲明了這個Activity可以在特定類型的資料上執行的操作。
組件可以有任意數量的Intent Filter,每個聲明一系列不同的功能。如果沒有任何過濾器,則只能被顯式聲明了目標組件名稱的Intent啟用。
對於在代碼中建立並註冊的廣播接收器,Intent Filter直接執行個體化為IntentFilter對象。所有其它的過濾器都在manifest檔案設定。
關於Intent Filter的其他資訊,請參閱:Intent和Intent Filter。