Android Activity 入門簡(jiǎn)介
Activity
Activity 是一個(gè)應(yīng)用組件,用戶可與其提供的屏幕進(jìn)行交互,以執(zhí)行撥打電話、拍攝照片、發(fā)送電子郵件或查看地圖等操作。 每個(gè) Activity 都會(huì)獲得一個(gè)用于繪制其用戶界面的窗口。窗口通常會(huì)充滿屏幕,但也可小于屏幕并浮動(dòng)在其他窗口之上。
一個(gè)應(yīng)用通常由多個(gè)彼此松散聯(lián)系的 Activity 組成。 一般會(huì)指定應(yīng)用中的某個(gè) Activity 為“主”Activity,即首次啟動(dòng)應(yīng)用時(shí)呈現(xiàn)給用戶的那個(gè) Activity。 而且每個(gè) Activity 均可啟動(dòng)另一個(gè) Activity,以便執(zhí)行不同的操作。 每次新 Activity 啟動(dòng)時(shí),前一 Activity 便會(huì)停止,但系統(tǒng)會(huì)在堆棧(“返回棧”)中保留該 Activity。 當(dāng)新 Activity 啟動(dòng)時(shí),系統(tǒng)會(huì)將其推送到返回棧上,并取得用戶焦點(diǎn)。 返回棧遵循基本的“后進(jìn)先出”堆棧機(jī)制,因此,當(dāng)用戶完成當(dāng)前 Activity 并按“返回”按鈕時(shí),系統(tǒng)會(huì)從堆棧中將其彈出(并銷毀),然后恢復(fù)前一 Activity。 (任務(wù)和返回棧文檔中對(duì)返回棧有更詳細(xì)的闡述。)
當(dāng)一個(gè) Activity 因某個(gè)新 Activity 啟動(dòng)而停止時(shí),系統(tǒng)會(huì)通過(guò)該 Activity 的生命周期回調(diào)方法通知其這一狀態(tài)變化。Activity 因狀態(tài)變化—系統(tǒng)是創(chuàng)建 Activity、停止 Activity、恢復(fù) Activity 還是銷毀 Activity— 而收到的回調(diào)方法可能有若干種,每一種回調(diào)都會(huì)為您提供執(zhí)行與該狀態(tài)變化相應(yīng)的特定操作的機(jī)會(huì)。 例如,停止時(shí),您的 Activity 應(yīng)釋放任何大型對(duì)象,例如網(wǎng)絡(luò)或數(shù)據(jù)庫(kù)連接。 當(dāng) Activity 恢復(fù)時(shí),您可以重新獲取所需資源,并恢復(fù)執(zhí)行中斷的操作。 這些狀態(tài)轉(zhuǎn)變都是 Activity 生命周期的一部分。
本文的其余部分闡述有關(guān)如何創(chuàng)建和使用 Activity 的基礎(chǔ)知識(shí)(包括對(duì) Activity 生命周期工作方式的全面闡述),以便您正確管理各種 Activity 狀態(tài)之間的轉(zhuǎn)變。
創(chuàng)建 Activity
要?jiǎng)?chuàng)建 Activity,您必須創(chuàng)建 Activity 的子類(或使用其現(xiàn)有子類)。您需要在子類中實(shí)現(xiàn) Activity 在其生命周期的各種狀態(tài)之間轉(zhuǎn)變時(shí)(例如創(chuàng)建 Activity、停止 Activity、恢復(fù) Activity 或銷毀 Activity 時(shí))系統(tǒng)調(diào)用的回調(diào)方法。 兩個(gè)最重要的回調(diào)方法是:
onCreate()
- 您必須實(shí)現(xiàn)此方法。系統(tǒng)會(huì)在創(chuàng)建您的 Activity 時(shí)調(diào)用此方法。您應(yīng)該在實(shí)現(xiàn)內(nèi)初始化 Activity 的必需組件。 最重要的是,您必須在此方法內(nèi)調(diào)用
setContentView(),以定義 Activity 用戶界面的布局。
onPause()
- 系統(tǒng)將此方法作為用戶離開(kāi) Activity 的第一個(gè)信號(hào)(但并不總是意味著 Activity 會(huì)被銷毀)進(jìn)行調(diào)用。 您通常應(yīng)該在此方法內(nèi)確認(rèn)在當(dāng)前用戶會(huì)話結(jié)束后仍然有效的任何更改(因?yàn)橛脩艨赡懿粫?huì)返回)。
您還應(yīng)使用幾種其他生命周期回調(diào)方法,以便提供流暢的 Activity 間用戶體驗(yàn),以及處理導(dǎo)致您的 Activity 停止甚至被銷毀的意外中斷。 后文的管理 Activity 生命周期部分對(duì)所有生命周期回調(diào)方法進(jìn)行了闡述。
實(shí)現(xiàn)用戶界面
Activity 的用戶界面是由層級(jí)式視圖 — 衍生自 View 類的對(duì)象 — 提供的。每個(gè)視圖都控制 Activity 窗口內(nèi)的特定矩形空間,可對(duì)用戶交互作出響應(yīng)。 例如,視圖可以是在用戶觸摸時(shí)啟動(dòng)某項(xiàng)操作的按鈕。
您可以利用 Android 提供的許多現(xiàn)成視圖設(shè)計(jì)和組織您的布局。“小部件”是提供按鈕、文本字段、復(fù)選框或僅僅是一幅圖像等屏幕視覺(jué)(交互式)元素的視圖。 “布局”是衍生自 ViewGroup 的視圖,為其子視圖提供唯一布局模型,例如線性布局、網(wǎng)格布局或相對(duì)布局。 您還可以為 View 類和 ViewGroup 類創(chuàng)建子類(或使用其現(xiàn)有子類)來(lái)自行創(chuàng)建小部件和布局,然后將它們應(yīng)用于您的 Activity 布局。
利用視圖定義布局的最常見(jiàn)方法是借助保存在您的應(yīng)用資源內(nèi)的 XML 布局文件。這樣一來(lái),您就可以將用戶界面的設(shè)計(jì)與定義 Activity 行為的源代碼分開(kāi)維護(hù)。 您可以通過(guò) setContentView() 將布局設(shè)置為 Activity 的 UI,從而傳遞布局的資源 ID。不過(guò),您也可以在 Activity 代碼中創(chuàng)建新 View,并通過(guò)將新 View 插入 ViewGroup 來(lái)創(chuàng)建視圖層次,然后通過(guò)將根 ViewGroup 傳遞到 setContentView() 來(lái)使用該布局。
在清單文件中聲明 Activity
您必須在清單文件中聲明您的 Activity,這樣系統(tǒng)才能訪問(wèn)它。 要聲明您的 Activity,請(qǐng)打開(kāi)您的清單文件,并將 <activity> 元素添加為 <application> 元素的子項(xiàng)。例如:
<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >您還可以在此元素中加入幾個(gè)其他特性,以定義 Activity 標(biāo)簽、Activity 圖標(biāo)或風(fēng)格主題等用于設(shè)置 Activity UI 風(fēng)格的屬性。 android:name 屬性是唯一必需的屬性—它指定 Activity 的類名。應(yīng)用一旦發(fā)布,即不應(yīng)更改此類名,否則,可能會(huì)破壞諸如應(yīng)用快捷方式等一些功能。
請(qǐng)參閱 元素參考文檔,了解有關(guān)在清單文件中聲明 Activity 的詳細(xì)信息。
使用 Intent 過(guò)濾器
元素還可指定各種 Intent 過(guò)濾器—使用 元素—以聲明其他應(yīng)用組件激活它的方法。
當(dāng)您使用 Android SDK 工具創(chuàng)建新應(yīng)用時(shí),系統(tǒng)自動(dòng)為您創(chuàng)建的存根 Activity 包含一個(gè) Intent 過(guò)濾器,其中聲明了該 Activity 響應(yīng)“主”操作且應(yīng)置于“launcher”類別內(nèi)。 Intent 過(guò)濾器的內(nèi)容如下所示:
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity><action> 元素指定這是應(yīng)用的“主”入口點(diǎn)。<category> 元素指定此 Activity 應(yīng)列入系統(tǒng)的應(yīng)用啟動(dòng)器內(nèi)(以便用戶啟動(dòng)該 Activity)。
如果您打算讓?xiě)?yīng)用成為獨(dú)立應(yīng)用,不允許其他應(yīng)用激活其 Activity,則您不需要任何其他 Intent 過(guò)濾器。 正如前例所示,只應(yīng)有一個(gè) Activity 具有“主”操作和“launcher”類別。 您不想提供給其他應(yīng)用的 Activity 不應(yīng)有任何 Intent 過(guò)濾器,您可以利用顯式 Intent 自行啟動(dòng)它們(下文對(duì)此做了闡述)。
不過(guò),如果您想讓 Activity 對(duì)衍生自其他應(yīng)用(以及您的自有應(yīng)用)的隱式 Intent 作出響應(yīng),則必須為 Activity 定義其他 Intent 過(guò)濾器。 對(duì)于您想要作出響應(yīng)的每一個(gè) Intent 類型,您都必須加入相應(yīng)的 <intent-filter>,其中包括一個(gè) 元素,還可選擇性地包括一個(gè) <category> 元素和 /或一個(gè) <data> 元素。這些元素指定您的 Activity 可以響應(yīng)的 Intent 類型。
啟動(dòng) Activity
您可以通過(guò)調(diào)用 startActivity(),并將其傳遞給描述您想啟動(dòng)的 Activity 的 Intent 來(lái)啟動(dòng)另一個(gè) Activity。Intent 對(duì)象會(huì)指定您想啟動(dòng)的具體 Activity 或描述您想執(zhí)行的操作類型(系統(tǒng)會(huì)為您選擇合適的 Activity,甚至是來(lái)自其他應(yīng)用的 Activity)。 Intent 對(duì)象還可能攜帶少量供所啟動(dòng) Activity 使用的數(shù)據(jù)。
在您的自有應(yīng)用內(nèi)工作時(shí),您經(jīng)常只需要啟動(dòng)某個(gè)已知 Activity。 您可以通過(guò)使用類名創(chuàng)建一個(gè)顯式定義您想啟動(dòng)的 Activity 的 Intent 對(duì)象來(lái)實(shí)現(xiàn)此目的。 例如,可以通過(guò)以下代碼讓一個(gè) Activity 啟動(dòng)另一個(gè)名為 SignInActivity 的 Activity:
Intent intent = new Intent(this, SignInActivity.class); startActivity(intent);
不過(guò),您的應(yīng)用可能還需要利用您的 Activity 數(shù)據(jù)執(zhí)行某項(xiàng)操作,例如發(fā)送電子郵件、短信或狀態(tài)更新。 在這種情況下,您的應(yīng)用自身可能不具有執(zhí)行此類操作所需的 Activity,因此您可以改為利用設(shè)備上其他應(yīng)用提供的 Activity 為您執(zhí)行這些操作。 這便是 Intent 對(duì)象的真正價(jià)值所在 — 您可以創(chuàng)建一個(gè) Intent 對(duì)象,對(duì)您想執(zhí)行的操作進(jìn)行描述,系統(tǒng)會(huì)從其他應(yīng)用啟動(dòng)相應(yīng)的 Activity。 如果有多個(gè) Activity 可以處理 Intent,則用戶可以選擇要使用哪一個(gè)。 例如,如果您想允許用戶發(fā)送電子郵件,可以創(chuàng)建以下 Intent:
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
添加到 Intent 中的 EXTRA_EMAIL extra 是一個(gè)字符串?dāng)?shù)組,其中包含應(yīng)將電子郵件發(fā)送到的電子郵件地址。 當(dāng)電子郵件應(yīng)用響應(yīng)此 Intent 時(shí),它會(huì)讀取 extra 中提供的字符串?dāng)?shù)組,并將它們放入電子郵件撰寫(xiě)窗體的“收件人”字段。 在這種情況下,電子郵件應(yīng)用的 Activity 啟動(dòng),并且當(dāng)用戶完成操作時(shí),您的 Activity startActivityForResult()(而非 startActivity())來(lái)啟動(dòng) Activity。 要想在隨后收到后續(xù) Activity 的結(jié)果,請(qǐng)實(shí)現(xiàn) onActivityResult() 回調(diào)方法。 當(dāng)后續(xù) Activity 完成時(shí),它會(huì)使用 Intent 向您的 onActivityResult() 方法返回結(jié)果。
例如,您可能希望用戶選取其中一位聯(lián)系人,以便您的 Activity 對(duì)該聯(lián)系人中的信息執(zhí)行某項(xiàng)操作。 您可以通過(guò)以下代碼創(chuàng)建此類 Intent 并處理結(jié)果:
private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content provider URI
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the request went well (OK) and the request was PICK_CONTACT_REQUEST
if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
// Perform a query to the contact's content provider for the contact's name
Cursor cursor = getContentResolver().query(data.getData(),
new String[] {Contacts.DISPLAY_NAME}, null, null, null);
if (cursor.moveToFirst()) { // True if the cursor is not empty
int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// Do something with the selected contact's name...
}
}
}上例顯示的是,您在處理 Activity 結(jié)果時(shí)應(yīng)該在 onActivityResult() 方法中使用的基本邏輯。 第一個(gè)條件檢查請(qǐng)求是否成功(如果成功,則resultCode 將為 RESULT_OK)以及此結(jié)果響應(yīng)的請(qǐng)求是否已知 — 在此情況下,requestCode與隨 startActivityForResult() 發(fā)送的第二個(gè)參數(shù)匹配。 代碼通過(guò)查詢 Intent 中返回的數(shù)據(jù)(data 參數(shù))從該處開(kāi)始處理 Activity 結(jié)果。
實(shí)際情況是,ContentResolver 對(duì)一個(gè)內(nèi)容提供程序執(zhí)行查詢,后者返回一個(gè) Cursor,讓查詢的數(shù)據(jù)能夠被讀取。如需了解詳細(xì)信息,請(qǐng)參閱內(nèi)容提供程序文檔。
結(jié)束 Activity
您可以通過(guò)調(diào)用 Activity 的 finish() 方法來(lái)結(jié)束該 Activity。您還可以通過(guò)調(diào)用 finishActivity() 結(jié)束您之前啟動(dòng)的另一個(gè) Activity。
- 注:在大多數(shù)情況下,您不應(yīng)使用這些方法顯式結(jié)束 Activity。 正如下文有關(guān) Activity 生命周期的部分所述,Android 系統(tǒng)會(huì)為您管理 Activity 的生命周期,因此您無(wú)需結(jié)束自己的 Activity。 調(diào)用這些方法可能對(duì)預(yù)期的用戶體驗(yàn)產(chǎn)生不良影響,因此只應(yīng)在您確實(shí)不想讓用戶返回此 Activity 實(shí)例時(shí)使用。 管理 Activity 生命周期
通過(guò)實(shí)現(xiàn)回調(diào)方法管理 Activity 的生命周期對(duì)開(kāi)發(fā)強(qiáng)大而又靈活的應(yīng)用至關(guān)重要。 Activity 的生命周期會(huì)直接受到 Activity 與其他 Activity、其任務(wù)及返回棧的關(guān)聯(lián)性的影響。
Activity 基本上以三種狀態(tài)存在:
- 繼續(xù)
此 Activity 位于屏幕前臺(tái)并具有用戶焦點(diǎn)。(有時(shí)也將此狀態(tài)稱作“運(yùn)行中”。)
- 暫停
另一個(gè) Activity 位于屏幕前臺(tái)并具有用戶焦點(diǎn),但此 Activity 仍可見(jiàn)。也就是說(shuō),另一個(gè) Activity 顯示在此 Activity 上方,并且該 Activity 部分透明或未覆蓋整個(gè)屏幕。 暫停的 Activity 處于完全活動(dòng)狀態(tài)(Activity 對(duì)象保留在內(nèi)存中,它保留了所有狀態(tài)和成員信息,并與窗口管理器保持連接),但在內(nèi)存極度不足的情況下,可能會(huì)被系統(tǒng)終止。
- 停止
該 Activity 被另一個(gè) Activity 完全遮蓋(該 Activity 目前位于“后臺(tái)”)。 已停止的 Activity 同樣仍處于活動(dòng)狀態(tài)(Activity 對(duì)象保留在內(nèi)存中,它保留了所有狀態(tài)和成員信息,但未與窗口管理器連接)。 不過(guò),它對(duì)用戶不再可見(jiàn),在他處需要內(nèi)存時(shí)可能會(huì)被系統(tǒng)終止。
如果 Activity 處于暫?;蛲V?fàn)顟B(tài),系統(tǒng)可通過(guò)要求其結(jié)束(調(diào)用其 finish() 方法)或直接終止其進(jìn)程,將其從內(nèi)存中刪除。(將其結(jié)束或終止后)再次打開(kāi) Activity 時(shí),必須重建。
實(shí)現(xiàn)生命周期回調(diào)
當(dāng)一個(gè) Activity 轉(zhuǎn)入和轉(zhuǎn)出上述不同狀態(tài)時(shí),系統(tǒng)會(huì)通過(guò)各種回調(diào)方法向其發(fā)出通知。 所有回調(diào)方法都是掛鉤,您可以在 Activity 狀態(tài)發(fā)生變化時(shí)替代這些掛鉤來(lái)執(zhí)行相應(yīng)操作。 以下框架 Activity 包括每一個(gè)基本生命周期方法:
public class ExampleActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
@Override
protected void onStart() {
super.onStart();
// The activity is about to become visible.
}
@Override
protected void onResume() {
super.onResume();
// The activity has become visible (it is now "resumed").
}
@Override
protected void onPause() {
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
@Override
protected void onStop() {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected void onDestroy() {
super.onDestroy();
// The activity is about to be destroyed.
}
}- 注:正如以上示例所示,您在實(shí)現(xiàn)這些生命周期方法時(shí)必須始終先調(diào)用超類實(shí)現(xiàn),然后再執(zhí)行任何操作。
這些方法共同定義 Activity 的整個(gè)生命周期。您可以通過(guò)實(shí)現(xiàn)這些方法監(jiān)控 Activity 生命周期中的三個(gè)嵌套循環(huán):
- Activity 的整個(gè)生命周期發(fā)生在 onCreate() 調(diào)用與 onDestroy() 調(diào)用之間。您的 Activity 應(yīng)在 onCreate() 中執(zhí)行“全局”狀態(tài)設(shè)置(例如定義布局),并釋放 onDestroy() 中的所有其余資源。例如,如果您的 Activity 有一個(gè)在后臺(tái)運(yùn)行的線程,用于從網(wǎng)絡(luò)上下載數(shù)據(jù),它可能會(huì)在 onCreate() 中創(chuàng)建該線程,然后在 onDestroy() 中停止該線程。
- Activity 的可見(jiàn)生命周期發(fā)生在 onStart() 調(diào)用與 onStop() 調(diào)用之間。在這段時(shí)間,用戶可以在屏幕上看到 Activity 并與其交互。 例如,當(dāng)一個(gè)新 Activity 啟動(dòng),并且此 Activity 不再可見(jiàn)時(shí),系統(tǒng)會(huì)調(diào)用 onStop()。您可以在調(diào)用這兩個(gè)方法之間保留向用戶顯示 Activity 所需的資源。 例如,您可以在 onStart() 中注冊(cè)一個(gè) BroadcastReceiver 以監(jiān)控影響 UI 的變化,并在用戶無(wú)法再看到您顯示的內(nèi)容時(shí)在 onStop() 中將其取消注冊(cè)。在 Activity 的整個(gè)生命周期,當(dāng) Activity 在對(duì)用戶可見(jiàn)和隱藏兩種狀態(tài)中交替變化時(shí),系統(tǒng)可能會(huì)多次調(diào)用 onStart() 和 onStop()。
- Activity 的前臺(tái)生命周期發(fā)生在 onResume() 調(diào)用與 onPause() 調(diào)用之間。在這段時(shí)間,Activity 位于屏幕上的所有其他 Activity 之前,并具有用戶輸入焦點(diǎn)。 Activity 可頻繁轉(zhuǎn)入和轉(zhuǎn)出前臺(tái) — 例如,當(dāng)設(shè)備轉(zhuǎn)入休眠狀態(tài)或出現(xiàn)對(duì)話框時(shí),系統(tǒng)會(huì)調(diào)用 onPause()。 由于此狀態(tài)可能經(jīng)常發(fā)生轉(zhuǎn)變,因此這兩個(gè)方法中應(yīng)采用適度輕量級(jí)的代碼,以避免因轉(zhuǎn)變速度慢而讓用戶等待。
下圖說(shuō)明了這些循環(huán)以及 Activity 在狀態(tài)轉(zhuǎn)變期間可能經(jīng)過(guò)的路徑。矩形表示回調(diào)方法,當(dāng) Activity 在不同狀態(tài)之間轉(zhuǎn)變時(shí),您可以實(shí)現(xiàn)這些方法來(lái)執(zhí)行操作。

下表列出了相同的生命周期回調(diào)方法,其中對(duì)每一種回調(diào)方法做了更詳細(xì)的描述,并說(shuō)明了每一種方法在 Activity 整個(gè)生命周期內(nèi)的位置,包括在回調(diào)方法完成后系統(tǒng)能否終止 Activity。
Activity 生命周期回調(diào)方法匯總表。
| 方法 | 說(shuō)明 | 是否能事后終止? | 后接 |
|---|---|---|---|
| onCreate() | 首次創(chuàng)建 Activity 時(shí)調(diào)用。 您應(yīng)該在此方法中執(zhí)行所有正常的靜態(tài)設(shè)置 — 創(chuàng)建視圖、將數(shù)據(jù)綁定到列表等等。 系統(tǒng)向此方法傳遞一個(gè) Bundle 對(duì)象,其中包含 Activity 的上一狀態(tài),不過(guò)前提是捕獲了該狀態(tài)(請(qǐng)參閱后文的保存 Activity 狀態(tài))。始終后接 onStart()。 | 否 | onStart() |
| onRestart() | 在 Activity 已停止并即將再次啟動(dòng)前調(diào)用。始終后接 onStart() | 否 | onStart() |
| onStart() | 在 Activity 即將對(duì)用戶可見(jiàn)之前調(diào)用。如果 Activity 轉(zhuǎn)入前臺(tái),則后接 onResume(),如果 Activity 轉(zhuǎn)入隱藏狀態(tài),則后接 onStop()。 | 否 | onResume() 或 onStop() |
| onPause() | 當(dāng)系統(tǒng)即將開(kāi)始繼續(xù)另一個(gè) Activity 時(shí)調(diào)用。 此方法通常用于確認(rèn)對(duì)持久性數(shù)據(jù)的未保存更改、停止動(dòng)畫(huà)以及其他可能消耗 CPU 的內(nèi)容,諸如此類。 它應(yīng)該非常迅速地執(zhí)行所需操作,因?yàn)樗祷睾?,下一個(gè) Activity 才能繼續(xù)執(zhí)行。如果 Activity 返回前臺(tái),則后接 onResume(),如果 Activity 轉(zhuǎn)入對(duì)用戶不可見(jiàn)狀態(tài),則后接 onStop()。 | 是 | onResume() 或 onStop() |
| onStop() | 在 Activity 對(duì)用戶不再可見(jiàn)時(shí)調(diào)用。如果 Activity 被銷毀,或另一個(gè) Activity(一個(gè)現(xiàn)有 Activity 或新 Activity)繼續(xù)執(zhí)行并將其覆蓋,就可能發(fā)生這種情況。如果 Activity 恢復(fù)與用戶的交互,則后接 onRestart(),如果 Activity 被銷毀,則后接 onDestroy()。 | 是 | onRestart()或 onDestroy() |
| onDestroy() | 在 Activity 被銷毀前調(diào)用。這是 Activity 將收到的最后調(diào)用。 當(dāng) Activity 結(jié)束(有人對(duì) Activity 調(diào)用了 finish()),或系統(tǒng)為節(jié)省空間而暫時(shí)銷毀該 Activity 實(shí)例時(shí),可能會(huì)調(diào)用它。 您可以通過(guò) isFinishing() 方法區(qū)分這兩種情形。 | 是 | 無(wú) |
名為“是否能事后終止?”的列表示系統(tǒng)是否能在不執(zhí)行另一行 Activity 代碼的情況下,在方法返回后隨時(shí)終止承載 Activity 的進(jìn)程。 有三個(gè)方法帶有“是”標(biāo)記:(onPause()、onStop() 和 onDestroy())。由于 onPause() 是這三個(gè)方法中的第一個(gè),因此 Activity 創(chuàng)建后,onPause() 必定成為最后調(diào)用的方法,然后才能終止進(jìn)程 — 如果系統(tǒng)在緊急情況下必須恢復(fù)內(nèi)存,則可能不會(huì)調(diào)用 onStop() 和 onDestroy()。因此,您應(yīng)該使用 onPause() 向存儲(chǔ)設(shè)備寫(xiě)入至關(guān)重要的持久性數(shù)據(jù)(例如用戶編輯)。不過(guò),您應(yīng)該對(duì) onPause() 調(diào)用期間必須保留的信息有所選擇,因?yàn)樵摲椒ㄖ械娜魏巫柚惯^(guò)程都會(huì)妨礙向下一個(gè) Activity 的轉(zhuǎn)變并拖慢用戶體驗(yàn)。
在是否能在事后終止?列中標(biāo)記為“否”的方法可從系統(tǒng)調(diào)用它們的一刻起防止承載 Activity 的進(jìn)程被終止。 因此,在從 onPause() 返回的時(shí)間到 onResume() 被調(diào)用的時(shí)間,系統(tǒng)可以終止 Activity。在 onPause() 被再次調(diào)用并返回前,將無(wú)法再次終止 Activity。 注:根據(jù)表 1 中的定義屬于技術(shù)上無(wú)法“終止”的 Activity 仍可能被系統(tǒng)終止 — 但這種情況只有在無(wú)任何其他資源的極端情況下才會(huì)發(fā)生。進(jìn)程和線程處理文檔對(duì)可能會(huì)終止 Activity 的情況做了更詳盡的闡述。
保存 Activity 狀態(tài)
管理 Activity 生命周期的引言部分簡(jiǎn)要提及,當(dāng) Activity 暫?;蛲V箷r(shí),Activity 的狀態(tài)會(huì)得到保留。 確實(shí)如此,因?yàn)楫?dāng) Activity 暫?;蛲V箷r(shí),Activity 對(duì)象仍保留在內(nèi)存中 — 有關(guān)其成員和當(dāng)前狀態(tài)的所有信息仍處于活動(dòng)狀態(tài)。 因此,用戶在 Activity 內(nèi)所做的任何更改都會(huì)得到保留,這樣一來(lái),當(dāng) Activity 返回前臺(tái)(當(dāng)它“繼續(xù)”)時(shí),這些更改仍然存在。
不過(guò),當(dāng)系統(tǒng)為了恢復(fù)內(nèi)存而銷毀某項(xiàng) Activity 時(shí),Activity 對(duì)象也會(huì)被銷毀,因此系統(tǒng)在繼續(xù) Activity 時(shí)根本無(wú)法讓其狀態(tài)保持完好,而是必須在用戶返回 Activity 時(shí)重建 Activity 對(duì)象。但用戶并不知道系統(tǒng)銷毀 Activity 后又對(duì)其進(jìn)行了重建,因此他們很可能認(rèn)為 Activity 狀態(tài)毫無(wú)變化。 在這種情況下,您可以實(shí)現(xiàn)另一個(gè)回調(diào)方法對(duì)有關(guān) Activity 狀態(tài)的信息進(jìn)行保存,以確保有關(guān) Activity 狀態(tài)的重要信息得到保留:onSaveInstanceState()。
系統(tǒng)會(huì)先調(diào)用 onSaveInstanceState(),然后再使 Activity 變得易于銷毀。系統(tǒng)會(huì)向該方法傳遞一個(gè) Bundle,您可以在其中使用putString() 和 putInt() 等方法以名稱-值對(duì)形式保存有關(guān) Activity 狀態(tài)的信息。然后,如果系統(tǒng)終止您的應(yīng)用進(jìn)程,并且用戶返回您的 Activity,則系統(tǒng)會(huì)重建該 Activity,并將 Bundle 同時(shí)傳遞給 onCreate() 和 onRestoreInstanceState()。您可以使用上述任一方法從 Bundle 提取您保存的狀態(tài)并恢復(fù)該 Activity 狀態(tài)。如果沒(méi)有狀態(tài)信息需要恢復(fù),則傳遞給您的 Bundle 是空值(如果是首次創(chuàng)建該 Activity,就會(huì)出現(xiàn)這種情況)。

圖 2. 在兩種情況下,Activity 重獲用戶焦點(diǎn)時(shí)可保持狀態(tài)完好:系統(tǒng)在銷毀 Activity 后重建 Activity,Activity 必須恢復(fù)之前保存的狀態(tài);系統(tǒng)停止 Activity 后繼續(xù)執(zhí)行 Activity,并且 Activity 狀態(tài)保持完好。
注:無(wú)法保證系統(tǒng)會(huì)在銷毀您的 Activity 前調(diào)用 onSaveInstanceState(),因?yàn)榇嬖诓恍枰4鏍顟B(tài)的情況(例如用戶使用“返回”按鈕離開(kāi)您的 Activity 時(shí),因?yàn)橛脩舻男袨槭窃陲@式關(guān)閉 Activity)。 如果系統(tǒng)調(diào)用 onSaveInstanceState(),它會(huì)在調(diào)用 onStop() 之前,并且可能會(huì)在調(diào)用 onPause() 之前進(jìn)行調(diào)用。
不過(guò),即使您什么都不做,也不實(shí)現(xiàn) onSaveInstanceState(),Activity 類的 onSaveInstanceState() 默認(rèn)實(shí)現(xiàn)也會(huì)恢復(fù)部分 Activity 狀態(tài)。具體地講,默認(rèn)實(shí)現(xiàn)會(huì)為布局中的每個(gè) View 調(diào)用相應(yīng)的 onSaveInstanceState() 方法,讓每個(gè)視圖都能提供有關(guān)自身的應(yīng)保存信息。Android 框架中幾乎每個(gè)小部件都會(huì)根據(jù)需要實(shí)現(xiàn)此方法,以便在重建 Activity 時(shí)自動(dòng)保存和恢復(fù)對(duì) UI 所做的任何可見(jiàn)更改。例如,EditText 小部件保存用戶輸入的任何文本,CheckBox 小部件保存復(fù)選框的選中或未選中狀態(tài)。您只需為想要保存其狀態(tài)的每個(gè)小部件提供一個(gè)唯一的 ID(通過(guò) android:id 屬性)。如果小部件沒(méi)有 ID,則系統(tǒng)無(wú)法保存其狀態(tài)。
您還可以通過(guò)將 android:saveEnabled 屬性設(shè)置為 "false" 或通過(guò)調(diào)用 setSaveEnabled() 方法顯式阻止布局內(nèi)的視圖保存其狀態(tài)。您通常不應(yīng)將該屬性停用,但如果您想以不同方式恢復(fù) Activity UI 的狀態(tài),就可能需要這樣做。
盡管 onSaveInstanceState() 的默認(rèn)實(shí)現(xiàn)會(huì)保存有關(guān)您的Activity UI 的有用信息,您可能仍需替換它以保存更多信息。例如,您可能需要保存在 Activity 生命周期內(nèi)發(fā)生了變化的成員值(它們可能與 UI 中恢復(fù)的值有關(guān)聯(lián),但默認(rèn)情況下系統(tǒng)不會(huì)恢復(fù)儲(chǔ)存這些 UI 值的成員)。
由于 onSaveInstanceState() 的默認(rèn)實(shí)現(xiàn)有助于保存 UI 的狀態(tài),因此如果您為了保存更多狀態(tài)信息而替換該方法,應(yīng)始終先調(diào)用 onSaveInstanceState() 的超類實(shí)現(xiàn),然后再執(zhí)行任何操作。 同樣,如果您替換 onRestoreInstanceState() 方法,也應(yīng)調(diào)用它的超類實(shí)現(xiàn),以便默認(rèn)實(shí)現(xiàn)能夠恢復(fù)視圖狀態(tài)。
注:由于無(wú)法保證系統(tǒng)會(huì)調(diào)用 onSaveInstanceState(),因此您只應(yīng)利用它來(lái)記錄 Activity 的瞬態(tài)(UI 的狀態(tài))— 切勿使用它來(lái)存儲(chǔ)持久性數(shù)據(jù),而應(yīng)使用 onPause() 在用戶離開(kāi) Activity 后存儲(chǔ)持久性數(shù)據(jù)(例如應(yīng)保存到數(shù)據(jù)庫(kù)的數(shù)據(jù))。
您只需旋轉(zhuǎn)設(shè)備,讓屏幕方向發(fā)生變化,就能有效地測(cè)試您的應(yīng)用的狀態(tài)恢復(fù)能力。 當(dāng)屏幕方向變化時(shí),系統(tǒng)會(huì)銷毀并重建 Activity,以便應(yīng)用可供新屏幕配置使用的備用資源。 單憑這一理由,您的 Activity 在重建時(shí)能否完全恢復(fù)其狀態(tài)就顯得非常重要,因?yàn)橛脩粼谑褂脩?yīng)用時(shí)經(jīng)常需要旋轉(zhuǎn)屏幕。
處理配置變更
有些設(shè)備配置可能會(huì)在運(yùn)行時(shí)發(fā)生變化(例如屏幕方向、鍵盤可用性及語(yǔ)言)。 發(fā)生此類變化時(shí),Android 會(huì)重建運(yùn)行中的 Activity(系統(tǒng)調(diào)用 onDestroy(),然后立即調(diào)用 onCreate())。此行為旨在通過(guò)利用您提供的備用資源(例如適用于不同屏幕方向和屏幕尺寸的不同布局)自動(dòng)重新加載您的應(yīng)用來(lái)幫助它適應(yīng)新配置。
如果您對(duì) Activity 進(jìn)行了適當(dāng)設(shè)計(jì),讓它能夠按以上所述處理屏幕方向變化帶來(lái)的重啟并恢復(fù) Activity 狀態(tài),那么在遭遇 Activity 生命周期中的其他意外事件時(shí),您的應(yīng)用將具有更強(qiáng)的適應(yīng)性。
正如上文所述,處理此類重啟的最佳方法是利用onSaveInstanceState() 和 onRestoreInstanceState()(或 onCreate())保存并恢復(fù) Activity 的狀態(tài)。
如需了解有關(guān)運(yùn)行時(shí)發(fā)生的配置變更以及應(yīng)對(duì)方法的詳細(xì)信息,請(qǐng)閱讀處理運(yùn)行時(shí)變更指南。
協(xié)調(diào) Activity
當(dāng)一個(gè) Activity 啟動(dòng)另一個(gè) Activity 時(shí),它們都會(huì)體驗(yàn)到生命周期轉(zhuǎn)變。第一個(gè) Activity 暫停并停止(但如果它在后臺(tái)仍然可見(jiàn),則不會(huì)停止)時(shí),同時(shí)系統(tǒng)會(huì)創(chuàng)建另一個(gè) Activity。 如果這些 Activity 共用保存到磁盤或其他地方的數(shù)據(jù),必須了解的是,在創(chuàng)建第二個(gè) Activity 前,第一個(gè) Activity 不會(huì)完全停止。更確切地說(shuō),啟動(dòng)第二個(gè) Activity 的過(guò)程與停止第一個(gè) Activity 的過(guò)程存在重疊。
生命周期回調(diào)的順序經(jīng)過(guò)明確定義,當(dāng)兩個(gè) Activity 位于同一進(jìn)程,并且由一個(gè) Activity 啟動(dòng)另一個(gè) Activity 時(shí),其定義尤其明確。 以下是當(dāng) Activity A 啟動(dòng) Activity B 時(shí)一系列操作的發(fā)生順序:
- Activity A 的 onPause() 方法執(zhí)行。
- Activity B 的 onCreate()、onStart() 和 onResume() 方法依次執(zhí)行。(Activity B 現(xiàn)在具有用戶焦點(diǎn)。)
- 然后,如果 Activity A 在屏幕上不再可見(jiàn),則其 onStop() 方法執(zhí)行。
您可以利用這種可預(yù)測(cè)的生命周期回調(diào)順序管理從一個(gè) Activity 到另一個(gè) Activity 的信息轉(zhuǎn)變。 例如,如果您必須在第一個(gè) Activity 停止時(shí)向數(shù)據(jù)庫(kù)寫(xiě)入數(shù)據(jù),以便下一個(gè) Activity 能夠讀取該數(shù)據(jù),則應(yīng)在 onPause() 而不是 onStop() 執(zhí)行期間向數(shù)據(jù)庫(kù)寫(xiě)入數(shù)據(jù)。
到此這篇關(guān)于Android Activity 介紹的文章就介紹到這了,更多相關(guān)Android Activity 介紹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android RecyclerView實(shí)現(xiàn)多種item布局的方法
本篇文章主要介紹了Android RecyclerView實(shí)現(xiàn)多種item布局的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
Ubuntu 14.04下創(chuàng)建Genymotion安卓虛擬機(jī)的步驟詳解
Android 模擬器一直以速度奇慢無(wú)比著稱,基本慢到不可用。本文介紹我一直在用的 Genymotion,速度不亞于真機(jī)。而且功能齊全,使用簡(jiǎn)單。下面這篇文章主要介紹了Ubuntu 14.04下創(chuàng)建Genymotion虛擬機(jī)的步驟,需要的朋友可以參考下。2017-03-03
Android編程之界面跳動(dòng)提示動(dòng)畫(huà)效果實(shí)現(xiàn)方法
這篇文章主要介紹了Android編程之界面跳動(dòng)提示動(dòng)畫(huà)效果實(shí)現(xiàn)方法,實(shí)例分析了Android動(dòng)畫(huà)效果的布局及功能相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
MPAndroidChart自定義圖表Chart的Attribute及Render繪制邏輯
這篇文章主要為大家介紹了MPAndroidChart自定義圖表Chart的Attribute及Render繪制邏輯,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android開(kāi)發(fā)gradle拉取依賴的加速配置
這篇文章主要為大家介紹了Android開(kāi)發(fā)gradle拉取依賴的加速配置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Android 動(dòng)態(tài)加載二維碼視圖生成快照的示例
本篇文章主要介紹了Android 動(dòng)態(tài)加載二維碼視圖生成快照的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
Android UI 實(shí)現(xiàn)老虎機(jī)詳解及實(shí)例代碼
這篇文章主要介紹了Android UI 實(shí)現(xiàn)老虎機(jī)詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
Android動(dòng)態(tài)更新Menu菜單的實(shí)現(xiàn)過(guò)程
菜單是用戶界面中最常見(jiàn)的元素之一,使用非常頻繁,下面這篇文章主要給大家介紹了關(guān)于Android動(dòng)態(tài)更新Menu菜單的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09

