Activity
https://developer.android.com/guide/components/activities.html
本文內(nèi)容
關(guān)鍵類
另請(qǐng)參閱
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)方法是:
您必須實(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 用戶界面的布局画株。
系統(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)使用該布局洲脂。
如需了解有關(guān)創(chuàng)建用戶界面的信息,請(qǐng)參閱用戶界面文檔剧包。
在清單文件中聲明 Activity
您必須在清單文件中聲明您的 Activity恐锦,這樣系統(tǒng)才能訪問(wèn)它雇毫。 要聲明您的 Activity,請(qǐng)打開(kāi)您的清單文件踩蔚,并將元素添加為元素的子項(xiàng)。例如:
...
...
您還可以在此元素中加入幾個(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)閱讀博客文章Things That Cannot Change[不能更改的內(nèi)容])暴凑。
請(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)置于“l(fā)auncher”類別內(nèi)嗦篱。 Intent 過(guò)濾器的內(nèi)容如下所示:
元素指定這是應(yīng)用的“主”入口點(diǎn)。元素指定此 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 具有“主”操作和“l(fā)auncher”類別。 您不想提供給其他應(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)的英遭,其中包括一個(gè)元素间护,還可選擇性地包括一個(gè)元素和/或一個(gè)元素。這些元素指定您的 Activity 可以響應(yīng)的 Intent 類型挖诸。
如需了解有關(guān)您的 Activity 如何響應(yīng) Intent 的詳細(xì)信息汁尺,請(qǐng)參閱Intent 和 Intent 過(guò)濾器文檔。
啟動(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:
Intentintent=newIntent(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:
Intentintent=newIntent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL,recipientArray);
startActivity(intent);
添加到 Intent 中的EXTRA_EMAILextra 是一個(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 會(huì)恢復(fù)執(zhí)行壹堰。
啟動(dòng) Activity 以獲得結(jié)果
有時(shí)拭卿,您可能需要從啟動(dòng)的 Activity 獲得結(jié)果。在這種情況下贱纠,請(qǐng)通過(guò)調(diào)用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é)果:
privatevoidpickContact(){
// Create an intent to "pick" a contact, as defined by the content provider URI
Intentintent=newIntent(Intent.ACTION_PICK,Contacts.CONTENT_URI);
startActivityForResult(intent,PICK_CONTACT_REQUEST);
}
@Override
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
// 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
Cursorcursor=getContentResolver().query(data.getData(),
newString[]{Contacts.DISPLAY_NAME},null,null,null);
if(cursor.moveToFirst()){// True if the cursor is not empty
intcolumnIndex=cursor.getColumnIndex(Contacts.DISPLAY_NAME);
Stringname=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)容提供程序文檔。
如需了解有關(guān) Intent 用法的詳細(xì)信息舵变,請(qǐng)參閱Intent 和 Intent 過(guò)濾器文檔酣溃。
結(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 處于暫停或停止?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è)基本生命周期方法:
publicclassExampleActivityextendsActivity{
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
// The activity is being created.
}
@Override
protectedvoidonStart(){
super.onStart();
// The activity is about to become visible.
}
@Override
protectedvoidonResume(){
super.onResume();
// The activity has become visible (it is now "resumed").
}
@Override
protectedvoidonPause(){
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
@Override
protectedvoidonStop(){
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protectedvoidonDestroy(){
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)變速度慢而讓用戶等待搅裙。
圖 1 說(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í)行操作好爬。
圖 1.Activity 生命周期局雄。
表 1 列出了相同的生命周期回調(diào)方法,其中對(duì)每一種回調(diào)方法做了更詳細(xì)的描述存炮,并說(shuō)明了每一種方法在 Activity 整個(gè)生命周期內(nèi)的位置炬搭,包括在回調(diào)方法完成后系統(tǒng)能否終止 Activity。
表 1.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()
onResume()在 Activity 即將開(kāi)始與用戶進(jìn)行交互之前調(diào)用。 此時(shí)洒擦,Activity 處于 Activity 堆棧的頂層椿争,并具有用戶輸入焦點(diǎn)。
始終后接onPause()秘遏。否onPause()
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 暫停或停止時(shí)勺良,Activity 的狀態(tài)會(huì)得到保留绰播。 確實(shí)如此,因?yàn)楫?dāng) Activity 暫蜕欣В或停止時(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ā)生變化(例如屏幕方向涝婉、鍵盤(pán)可用性及語(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 共用保存到磁盤(pán)或其他地方的數(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ù)。