Android Activity

Activity

https://developer.android.com/guide/components/activities.html

本文內(nèi)容

創(chuàng)建 Activity

實(shí)現(xiàn)用戶界面

在清單文件中聲明 Activity

啟動(dòng) Activity

啟動(dòng) Activity 以獲得結(jié)果

結(jié)束 Activity

管理 Activity 生命周期

實(shí)現(xiàn)生命周期回調(diào)

保存 Activity 狀態(tài)

處理配置變更

協(xié)調(diào) Activity

關(guān)鍵類

Activity

另請(qǐng)參閱

任務(wù)和返回棧

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)使用該布局洲脂。

如需了解有關(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ù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沪摄,一起剝皮案震驚了整個(gè)濱河市躯嫉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌杨拐,老刑警劉巖祈餐,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異哄陶,居然都是意外死亡帆阳,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)屋吨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蜒谤,“玉大人山宾,你說(shuō)我怎么就攤上這事△⒒眨” “怎么了资锰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)阶祭。 經(jīng)常有香客問(wèn)我台妆,道長(zhǎng),這世上最難降的妖魔是什么胖翰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任接剩,我火速辦了婚禮,結(jié)果婚禮上萨咳,老公的妹妹穿的比我還像新娘懊缺。我一直安慰自己,他們只是感情好培他,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布鹃两。 她就那樣靜靜地躺著,像睡著了一般舀凛。 火紅的嫁衣襯著肌膚如雪俊扳。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天猛遍,我揣著相機(jī)與錄音馋记,去河邊找鬼。 笑死懊烤,一個(gè)胖子當(dāng)著我的面吹牛梯醒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腌紧,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼茸习,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了壁肋?” 一聲冷哼從身側(cè)響起号胚,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎浸遗,沒(méi)想到半個(gè)月后猫胁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乙帮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年杜漠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了极景。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片察净。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驾茴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氢卡,到底是詐尸還是另有隱情锈至,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布译秦,位于F島的核電站峡捡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏筑悴。R本人自食惡果不足惜们拙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阁吝。 院中可真熱鬧砚婆,春花似錦、人聲如沸突勇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甲馋。三九已至埂奈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間定躏,已是汗流浹背账磺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痊远,地道東北人绑谣。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拗引,于是被迫代替她去往敵國(guó)和親借宵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容