
在前面的文章里我們知道了 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ì)在堆棧(“返回?!保┲斜A粼?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。
而對(duì)于生命周期我們知道了當(dāng)一個(gè) Activity 因某個(gè)新 Activity 啟動(dòng)而停止時(shí),系統(tǒng)會(huì)通過(guò)該 Activity 的生命周期回調(diào)方法通知其這一狀態(tài)變化。Activity 因狀態(tài)變化而收到的回調(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 生命周期的一部分。
我們本篇會(huì)闡述有關(guān)如何創(chuàng)建和使用 Activity 的基礎(chǔ)知識(shí)(包括 Activity的啟動(dòng)和銷毀、暫停與恢復(fù)、停止與重啟、重新創(chuàng)建以及一些其他問(wèn)題),這樣我們就可以正確管理各種 Activity 狀態(tài)之間的轉(zhuǎn)變了。
一、 Activity的啟動(dòng)和銷毀
編寫過(guò)Java程序的小伙伴都知道,我們每個(gè)Java程序都有一個(gè)主入口,比如說(shuō)Main()。但是Android編程不同于使用 Main() 方法啟動(dòng)應(yīng)用的其他編程范例,Android 系統(tǒng)會(huì)通過(guò)調(diào)用對(duì)應(yīng)于其生命周期中特定階段的特定回調(diào)方法在 Activity 實(shí)例中啟動(dòng)代碼。 有一系列可啟動(dòng)Activity的回調(diào)方法,以及一系列可分解Activity的回調(diào)方法。
1、生命周期回調(diào)
在Activity的生命周期中,系統(tǒng)會(huì)按類似于階梯金字塔的順序調(diào)用一組核心的生命周期方法。也就是說(shuō),Activity生命周期的每個(gè)階段就是金字塔上的一階,當(dāng)系統(tǒng)創(chuàng)建新Activity實(shí)例時(shí),每個(gè)回調(diào)方法會(huì)將Activity狀態(tài)向頂端移動(dòng)一階,而金字塔的頂端就是Activity在前臺(tái)運(yùn)行并且用戶可以與其交互的時(shí)間點(diǎn)。
當(dāng)用戶開始離開Activity時(shí),系統(tǒng)會(huì)調(diào)用其他方法在金字塔中將Activity狀態(tài)下移,從而銷毀Activity。在有些情況下,Activity將只在金字塔中部分下移并等待(比如,當(dāng)用戶切換到其他應(yīng)用時(shí)),Activity可從該點(diǎn)開始移回頂端(如果用戶返回到該Activity),并在用戶停止的位置繼續(xù)。

如上圖所示,對(duì)于用于將Activity朝頂端的“繼續(xù)”狀態(tài)移動(dòng)一階的每個(gè)回調(diào),都有一種將Activity下移一階的回調(diào)方法與之對(duì)應(yīng),也就是說(shuō)Activity還可以從“暫?!焙汀巴V埂睜顟B(tài)回到剛才的狀態(tài)。
根據(jù)Activity的復(fù)雜程度,您可能不需要實(shí)現(xiàn)所有生命周期方法。但是了解每個(gè)方法并實(shí)現(xiàn)確保我們的應(yīng)用按照用戶期望的方式運(yùn)行的方法是非常重要的。正確實(shí)現(xiàn)我們的Activity生命周期方法可確保我們的應(yīng)用按照以下幾種方式良好運(yùn)行。
良好運(yùn)行的幾種方式:
- 如果用戶在使用我們的應(yīng)用時(shí)接聽來(lái)電或切換到另一個(gè)應(yīng)用,它不會(huì)崩潰。
- 在用戶未主動(dòng)使用它時(shí)不會(huì)消耗寶貴的系統(tǒng)資源。
- 如果用戶離開我們的應(yīng)用并稍后返回,不會(huì)丟失用戶的進(jìn)度。
- 當(dāng)屏幕在橫向和縱向之間旋轉(zhuǎn)時(shí),不會(huì)崩潰或丟失用戶的進(jìn)度。
正如我們將要在以下課程中要學(xué)習(xí)的,Activity會(huì)在上圖所示不同狀態(tài)之間過(guò)渡,但是這些狀態(tài)中只有三種可以是靜態(tài)。也就是說(shuō),Activity只能在三種狀態(tài)之一下存活很長(zhǎng)時(shí)間。
三種存活時(shí)間長(zhǎng)的狀態(tài):
- Resumed:在這種狀態(tài)下,Activity處于前臺(tái),且用戶可以與其交互,有時(shí)也稱為“運(yùn)行”狀態(tài)。
- Paused:在這種狀態(tài)下,Activity被在前臺(tái)中處于半透明狀態(tài)或者未覆蓋整個(gè)屏幕的另一個(gè)Activity—部分阻擋,暫停的Activity不會(huì)接收用戶輸入并且無(wú)法執(zhí)行任何代碼。
- Stopped:在這種狀態(tài)下,Activity被完全隱藏并且對(duì)用戶不可見;它被視為處于后臺(tái)。停止時(shí),Activity實(shí)例及其諸如成員變量等所有狀態(tài)信息將保留,但它無(wú)法執(zhí)行任何代碼。
其它狀態(tài) (Created與Started)都是短暫的瞬態(tài),系統(tǒng)會(huì)通過(guò)調(diào)用下一個(gè)生命周期回調(diào)方法從這些狀態(tài)快速移到下一個(gè)狀態(tài)。 也就是說(shuō),在系統(tǒng)調(diào)用 onCreate() 之后,它會(huì)快速調(diào)用 onStart(),緊接著快速調(diào)用 onResume()。
生命周期回調(diào)部分到此為止,現(xiàn)在我們將開始學(xué)習(xí)特定生命周期行為的一些知識(shí)。
2、指定程序首次啟動(dòng)的Activity
當(dāng)用戶在主界面點(diǎn)擊程序圖標(biāo)時(shí),系統(tǒng)會(huì)調(diào)用App中被聲明為"launcher" (或者 "main") Activity中的 onCreate() 方法,這個(gè)Activity就是被用來(lái)當(dāng)作程序的主要進(jìn)入點(diǎn)的Activity。我們可以在 AndroidManifest.xml 中定義作為主Activity的Activity。
這個(gè)main activity必須在manifest使用包括 MAIN action 與 LAUNCHER category 的 <intent-filte 標(biāo)簽來(lái)聲明,例如:
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
注意:當(dāng)你使用Android SDK工具來(lái)創(chuàng)建Android工程時(shí),工程中就包含了一個(gè)默認(rèn)的聲明有這個(gè)filter的activity類。
當(dāng)然,這也就意味著如果程序中沒(méi)有聲明了 MAIN action 或者 LAUNCHER category的activity,那么在設(shè)備的主界面列表里面就不會(huì)呈現(xiàn)App圖標(biāo)。
3、創(chuàng)建一個(gè)Activity實(shí)例
大多數(shù)App包括多個(gè) Activity,使用戶可以執(zhí)行不同的動(dòng)作。不論這個(gè)Activity是當(dāng)用戶點(diǎn)擊應(yīng)用圖標(biāo)創(chuàng)建的 Main Activtiy 還是為了響應(yīng)用戶行為而創(chuàng)建的其他 Activity,系統(tǒng)都會(huì)調(diào)用新 Activity 實(shí)例中的 onCreate() 方法。所以我們必須實(shí)現(xiàn)onCreate()方法來(lái)執(zhí)行程序啟動(dòng)所需要的基本邏輯,例如可以在 onCreate() 方法中定義UI以及實(shí)例化類成員變量。
我們用下面的onCreate()方法演示為了建立一個(gè) Activity 所需要的一些基礎(chǔ)操作,如聲明UI元素、定義成員變量、配置UI等。當(dāng)然** onCreate 里面要盡量少做事情,避免程序啟動(dòng)太久都看不到界面**:
TextView mTextView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
mTextView = (TextView) findViewById(R.id.text_message);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
}
}
我們的 Activity 不會(huì)在 Created 或者 Started 狀態(tài)停留。從技術(shù)上來(lái)說(shuō),Activity 在 onStart() 被調(diào)用后開始被用戶可見,但是 onResume() 會(huì)迅速被執(zhí)行使得 Activity 停留在 Resumed 狀態(tài),直到一些因素發(fā)生變化才會(huì)改變這個(gè)狀態(tài),例如接收到一個(gè)來(lái)電,用戶切換到另外一個(gè)Activity,或者是設(shè)備屏幕關(guān)閉等。

上圖顯示了 onCreate()、onStart() 和 onResume() 是如何執(zhí)行的。當(dāng)這三個(gè)順序執(zhí)行的回調(diào)函數(shù)完成后,Activity會(huì)到達(dá) Resumed 狀態(tài)。當(dāng)然,如果你足夠細(xì)心的話,你會(huì)發(fā)現(xiàn) onCreate() 方法包含了一個(gè)參數(shù)叫做 savedInstanceState,這部分的內(nèi)容將會(huì)在后面的文章中涉及到。
4、銷毀Activity
Activity 的第一個(gè)生命周期回調(diào)函數(shù)是 onCreate(),它的最后一個(gè)回調(diào)是 onDestroy(),當(dāng)收到需要將該 Activity 徹底移除的信號(hào)時(shí),系統(tǒng)會(huì)調(diào)用這個(gè)方法。
大多數(shù) App 并不需要實(shí)現(xiàn)這個(gè)方法,因?yàn)榫植款惖?references 會(huì)隨著 Activity 的銷毀而銷毀,并且我們的 Activity 應(yīng)該在 onPause() 與 onStop() 中執(zhí)行清除 Activity 資源的操作。然而,如果 Activity 含有在 onCreate 調(diào)用時(shí)創(chuàng)建的后臺(tái)線程、打開的數(shù)據(jù)庫(kù)、請(qǐng)求的網(wǎng)絡(luò)連接等,則應(yīng)該在 onDestroy() 時(shí)進(jìn)行資源清理,以此避免內(nèi)存泄漏。
@Override
public void onDestroy() {
super.onDestroy();
android.os.Debug.stopMethodTracing();
}
注意:除非程序在 onCreate() 方法里面就調(diào)用了 finish() 方法,系統(tǒng)通常是在執(zhí)行了onPause() 與 onStop() 之后再調(diào)用 onDestroy() 。在某些情況下,例如我們的 Activity 只是做了一個(gè)臨時(shí)的邏輯跳轉(zhuǎn)的功能,它只是用來(lái)決定跳轉(zhuǎn)到哪一個(gè) Activity,這樣的話就需要在 onCreate 里面調(diào)用 finish 方法,這樣系統(tǒng)會(huì)直接調(diào)用 onDestory,跳過(guò)生命周期中的其它方法。
二、Activity的暫停與恢復(fù)
在正常使用App時(shí),前端的Activity有時(shí)會(huì)被其他可見的組件阻塞,從而導(dǎo)致當(dāng)前的Activity進(jìn)入Pause狀態(tài)。例如,當(dāng)打開一個(gè)半透明的Activity時(shí)(比如對(duì)話框),之前的Activity會(huì)被暫停。 只要之前的Activity仍然被部分可見,這個(gè)Activity就會(huì)一直處于Paused狀態(tài)。
然而,一旦之前的Activity被完全阻塞并不可見時(shí),則其會(huì)進(jìn)入Stop狀態(tài)(這是下一個(gè)話題了)。Activity一旦進(jìn)入Paused狀態(tài),系統(tǒng)就會(huì)調(diào)用Activity中的onPause()方法,該方法中可以停止不應(yīng)該在暫停過(guò)程中執(zhí)行的操作,如暫停視頻播放,或者保存那些有可能需要長(zhǎng)期保存的信息。如果用戶從暫停狀態(tài)回到當(dāng)前Activity,系統(tǒng)應(yīng)該恢復(fù)那些數(shù)據(jù)并執(zhí)行onResume()方法。

注意: 當(dāng)我們的Activity收到調(diào)用onPause()的信號(hào)時(shí),那意味著Activity將被暫停一段時(shí)間,并且用戶很可能會(huì)在將來(lái)回到我們的Activity。然而,這也是用戶要離開我們的Activtiy的第一個(gè)信號(hào)。
當(dāng)另一個(gè)半透明的Activity阻塞當(dāng)前Activity時(shí),系統(tǒng)會(huì)調(diào)用onPause()方法并且當(dāng)前這個(gè)Activity會(huì)停留在 Paused 狀態(tài)(1)。如果用戶在這個(gè)Activity還是在Paused 狀態(tài)時(shí)回到這個(gè)Activity,系統(tǒng)則會(huì)調(diào)用它的onResume() (2)。
1、暫停Activity
當(dāng)系統(tǒng)調(diào)用Activity中的onPause()時(shí),從技術(shù)上來(lái)講,這意味著Activity仍然處于部分可見的狀態(tài),但更多時(shí)候意味著用戶正在離開這個(gè)Activity,并馬上會(huì)進(jìn)入Stopped 狀態(tài),通常應(yīng)該在onPause() 回調(diào)方法里面做以下事情:
onPause() 回調(diào)方法里做的事:
- 停止動(dòng)畫或者是其他正在運(yùn)行的操作,那些都會(huì)導(dǎo)致CPU的浪費(fèi)。
- 提交在用戶離開時(shí)期待保存的內(nèi)容(例如郵件草稿)。
- 釋放系統(tǒng)資源,例如 Broadcast Receivers、Sensors (比如GPS) 或者其他任何會(huì)影響到電量的資源。
例如, 如果程序使用Camera時(shí),onPause()會(huì)是一個(gè)比較好的地方去做那些釋放資源的操作:
@Override
public void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.release()
mCamera = null;
}
}
通常來(lái)講,我們不應(yīng)該使用onPause()來(lái)保存用戶改變的數(shù)據(jù) (例如填入表格中的個(gè)人信息) 到永久存儲(chǔ)(文件或者數(shù)據(jù)庫(kù))上,而僅僅當(dāng)確認(rèn)用戶期待那些改變能夠被自動(dòng)保存的時(shí)候(例如正在撰寫郵件草稿),才把那些數(shù)據(jù)存到永久存儲(chǔ) 。但是,我們應(yīng)該避免在onPause()時(shí)執(zhí)行CPU高負(fù)荷的工作,例如寫數(shù)據(jù)到數(shù)據(jù)庫(kù),因?yàn)樗鼤?huì)導(dǎo)致切換到下一個(gè)Activity變得緩慢,所以應(yīng)該把那些高負(fù)荷的工作放到onStop()去做。
注意:當(dāng)Activity處于暫停狀態(tài)時(shí),Activity的實(shí)例是駐留在內(nèi)存中的,并且在Activity恢復(fù)的時(shí)候會(huì)被重新調(diào)用,所以我們不需要在恢復(fù)到Resumed狀態(tài)的一系列回調(diào)方法中重新初始化組件。
2、恢復(fù)Activity
當(dāng)用戶從Paused狀態(tài)恢復(fù)Activity時(shí),系統(tǒng)會(huì)調(diào)用onResume()方法。需要我們注意的是,系統(tǒng)每次調(diào)用這個(gè)方法時(shí),Activity都是處于前臺(tái)的,包括第一次創(chuàng)建的時(shí)候。所以,應(yīng)該在onResume()中初始化那些在onPause方法里面釋放掉的組件,并執(zhí)行那些Activity每次進(jìn)入Resumed 狀態(tài)都需要的初始化動(dòng)作 (例如開始動(dòng)畫與初始化那些只有在獲取用戶焦點(diǎn)時(shí)才需要的組件)。
下面的onResume()的例子是與上面的onPause()例子相對(duì)應(yīng)的:
@Override
public void onResume() {
super.onResume();
if (mCamera == null) {
initializeCamera();
}
}
三、Activity的停止與重啟
恰當(dāng)?shù)耐V古c重啟我們的Activity是很重要的,在Activity生命周期中,他們能確保用戶感知到程序的存在并不會(huì)丟失他們的進(jìn)度。在下面一些關(guān)鍵的場(chǎng)景中會(huì)涉及到停止與重啟:
停止與重啟的場(chǎng)景:
- 用戶打開最近使用App的菜單并從我們的App切換到另外一個(gè)App,這個(gè)時(shí)候我們的App是被停止的。如果用戶通過(guò)手機(jī)主界面的啟動(dòng)程序圖標(biāo)或者最近使用程序的窗口回到我們的App,那么我們的Activity會(huì)重啟。
- 用戶在我們的App里面執(zhí)行啟動(dòng)一個(gè)新Activity的操作,當(dāng)前Activity會(huì)在第二個(gè)Activity被創(chuàng)建后Stop。如果用戶點(diǎn)擊Back按鈕,第一個(gè)Activtiy會(huì)被重啟。
- 用戶在使用我們的app時(shí)接收到一個(gè)來(lái)電通話.
Activity 類提供了 onStop() 與 onRestart() 方法來(lái)允許在 Activity 停止與重啟時(shí)進(jìn)行調(diào)用。不同于暫停狀態(tài)的部分阻塞UI,停止?fàn)顟B(tài)是UI不再可見并且用戶的焦點(diǎn)轉(zhuǎn)移到另一個(gè)Activity中。
注意:因?yàn)橄到y(tǒng)在Activity停止時(shí)會(huì)在內(nèi)存中保存Activity的實(shí)例,所以有時(shí)不需要實(shí)現(xiàn)onStop()、onRestart()甚至是onStart()方法,因?yàn)榇蠖鄶?shù)的Activity相對(duì)比較簡(jiǎn)單,Activity會(huì)自己停止與重啟,我們只需要使用onPause()來(lái)停止正在運(yùn)行的動(dòng)作并斷開系統(tǒng)資源鏈接。

上圖顯示:當(dāng)用戶離開我們的Activity時(shí),系統(tǒng)會(huì)調(diào)用onStop()來(lái)停止Activity (1),這個(gè)時(shí)候如果用戶返回,系統(tǒng)會(huì)調(diào)用onRestart()(2),之后會(huì)迅速調(diào)用 onStart()(3) 與 onResume()(4)。也就是說(shuō):無(wú)論什么原因?qū)е翧ctivity停止,系統(tǒng)總是會(huì)在onStop()之前調(diào)用onPause()方法。
2、停止Activity
當(dāng)Activity調(diào)用onStop()方法時(shí),Activity變得不再可見,并且應(yīng)該釋放那些不再需要的所有資源。一旦Activity停止了,系統(tǒng)會(huì)在需要內(nèi)存空間時(shí)摧毀它的實(shí)例(和棧結(jié)構(gòu)有關(guān),通常back操作會(huì)導(dǎo)致前一個(gè)Activity被銷毀)。極端情況下,系統(tǒng)會(huì)直接殺死我們的App進(jìn)程,并不執(zhí)行Activity的onDestroy()回調(diào)方法, 因此我們需要使用onStop()來(lái)釋放資源,從而避免內(nèi)存泄漏。盡管onPause()方法是在onStop()之前調(diào)用,我們應(yīng)該使用onStop()來(lái)執(zhí)行那些CPU高負(fù)荷的關(guān)閉操作,例如往數(shù)據(jù)庫(kù)寫信息。
下面是一個(gè)在onStop()的方法里面保存筆記草稿到持久化內(nèi)存的示例:
@Override
protected void onStop() {
super.onStop();
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
getContentResolver().update(mUri, values, null, null);
}
Activity已經(jīng)停止后,Activity 對(duì)象會(huì)保存在內(nèi)存中,并在Activity Resume時(shí)被重新調(diào)用。我們不需要在恢復(fù)到Resumed狀態(tài)前重新初始化那些被保存在內(nèi)存中的組件。系統(tǒng)同樣保存了每一個(gè)在布局中的視圖的當(dāng)前狀態(tài),如果用戶在EditText組件中輸入了text,它會(huì)被保存,因此不需要保存與恢復(fù)它。
注意:即使系統(tǒng)會(huì)在Activity stop時(shí)停止這個(gè)Activity,它仍然會(huì)保存 View 對(duì)象的狀態(tài)(比如 EditText 中的文字到一個(gè) Bundle 中,并且在用戶返回這個(gè)Activity時(shí)恢復(fù)它們(后面的文章會(huì)介紹在Activity銷毀與重新建立時(shí)如何使用 Bundle 來(lái)保存其他數(shù)據(jù)的狀態(tài)。
3、啟動(dòng)與重啟Activity
當(dāng)Activity從Stopped狀態(tài)回到前臺(tái)時(shí),它會(huì)調(diào)用onRestart(),系統(tǒng)再調(diào)用onStart()方法,onStart()方法會(huì)在每次Activity可見時(shí)都會(huì)被調(diào)用。onRestart()方法則是只在Activity從stopped狀態(tài)恢復(fù)時(shí)才會(huì)被調(diào)用,因此我們可以使用它來(lái)執(zhí)行一些特殊的恢復(fù)工作,請(qǐng)注意之前是被Stopped而不是Destrory。
使用onRestart()來(lái)恢復(fù)Activity狀態(tài)是不太常見的,因此對(duì)于這個(gè)方法如何使用沒(méi)有任何的指導(dǎo)。然而,因?yàn)閛nStop()方法應(yīng)該做清除所有Activity資源的操作,我們需要在重啟Activtiy時(shí)重新實(shí)例化那些被清除的資源,同樣,我們也需要在Activity第一次創(chuàng)建時(shí)實(shí)例化那些資源。介于上面的原因,應(yīng)該使用onStart()作為onStop()所對(duì)應(yīng)方法。因?yàn)橄到y(tǒng)會(huì)在創(chuàng)建Activity與從停止?fàn)顟B(tài)重啟Activity時(shí)都會(huì)調(diào)用onStart()。也就是說(shuō),我們?cè)趏nStop里面做了哪些清除的操作,就該在onStart里面重新把那些清除掉的資源重新創(chuàng)建出來(lái)。
因?yàn)橛脩艉芸赡茉诨氐竭@個(gè)Activity之前已經(jīng)過(guò)了很長(zhǎng)一段時(shí)間,所以onStart()方法是一個(gè)比較好的地方來(lái)驗(yàn)證某些必須的系統(tǒng)特性是否可用:
@Override
protected void onStart() {
super.onStart();
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) {
}
}
@Override
protected void onRestart() {
super.onRestart();
}
當(dāng)系統(tǒng)Destory我們的Activity,它會(huì)為Activity調(diào)用onDestroy()方法。因?yàn)槲覀儠?huì)在onStop方法里面做釋放資源的操作,那么onDestory方法則是我們最后去清除那些可能導(dǎo)致內(nèi)存泄漏的地方,因此需要確保那些線程都被Destroyed并且所有的操作都被停止。
四、Activity的重新創(chuàng)建
有幾個(gè)場(chǎng)景Activity是由于正常的程序行為而被Destory的。例如當(dāng)用戶點(diǎn)擊返回按鈕或者是Activity通過(guò)調(diào)用finish()來(lái)發(fā)出停止信號(hào)。系統(tǒng)也有可能會(huì)在Activity處于Stop狀態(tài)且長(zhǎng)時(shí)間不被使用,或者是在前臺(tái)Activity需要更多系統(tǒng)資源的時(shí)關(guān)閉后臺(tái)進(jìn)程,以圖獲取更多的內(nèi)存。當(dāng)Activity是因?yàn)橛脩酎c(diǎn)擊Back按鈕或者是Activity通過(guò)調(diào)用Finish()結(jié)束自己時(shí),系統(tǒng)就丟失了對(duì)Activity實(shí)例的引用,因?yàn)檫@一行為意味著不再需要這個(gè)Activity了。
然而,如果因?yàn)橄到y(tǒng)資源緊張而導(dǎo)致Activity的Destory, 系統(tǒng)會(huì)在用戶回到這個(gè)Activity時(shí)有這個(gè)Activity存在過(guò)的記錄,系統(tǒng)會(huì)使用那些保存的記錄數(shù)據(jù)(描述了當(dāng)Activity被Destory時(shí)的狀態(tài))來(lái)重新創(chuàng)建一個(gè)新的Activity實(shí)例。那些被系統(tǒng)用來(lái)恢復(fù)之前狀態(tài)而保存的數(shù)據(jù)被叫做 "instance state" ,它是一些存放在Bundle對(duì)象中的鍵值對(duì)。
注意:我們的Activity會(huì)在每次旋轉(zhuǎn)屏幕時(shí)被Destroyed與Recreated,當(dāng)屏幕改變方向時(shí),系統(tǒng)會(huì)Destory與Recreate前臺(tái)的Activity,因?yàn)槠聊慌渲帽桓淖儯愕腁ctivity可能需要加載另一些替代的資源。
默認(rèn)情況下,系統(tǒng)使用 Bundle 實(shí)例來(lái)保存每一個(gè)View(視圖)對(duì)象中的信息(例如輸入EditText 中的文本內(nèi)容)。因此,如果Activity被Destroyed與Recreated,則layout的狀態(tài)信息會(huì)自動(dòng)恢復(fù)到之前的狀態(tài)。然而,Activity也許存在更多你想要恢復(fù)的狀態(tài)信息,例如記錄用戶Progress的成員變量。
注意:為了使Android系統(tǒng)能夠恢復(fù)Activity中的View的狀態(tài),每個(gè)View都必須有一個(gè)唯一ID,由android:id定義。
為了可以保存額外更多的數(shù)據(jù)到saved instance state,在Activity的生命周期里面存在一個(gè)額外的回調(diào)函數(shù),我們必須重寫這個(gè)函數(shù)。該回調(diào)函數(shù)并沒(méi)有在前面的圖片示例中顯示,這個(gè)方法是 onSaveInstanceState() ,當(dāng)用戶離開Activity時(shí),系統(tǒng)會(huì)調(diào)用它。當(dāng)系統(tǒng)調(diào)用這個(gè)函數(shù)時(shí),系統(tǒng)會(huì)在Activity被異常Destory時(shí)傳遞 Bundle 對(duì)象,這樣我們就可以增加額外的信息到Bundle中并保存到系統(tǒng)中。若系統(tǒng)在Activity被Destory之后想重新創(chuàng)建這個(gè)Activity實(shí)例,之前的Bundle對(duì)象會(huì)被傳遞到你我們Activity的 onRestoreInstanceState() 方法與 onCreate() 方法中。

注意: 當(dāng)系統(tǒng)開始停止Activity時(shí),只有在Activity實(shí)例需要重新創(chuàng)建的情況下才會(huì)調(diào)用到onSaveInstanceState()(1) ,在這個(gè)方法里面可以指定額外的狀態(tài)數(shù)據(jù)到Bunde中。如果這個(gè)Activity被Destroyed然后這個(gè)實(shí)例又需要被重新創(chuàng)建時(shí),系統(tǒng)會(huì)傳遞在 (1) 中的狀態(tài)數(shù)據(jù)到 onCreate() (2) 與 onRestoreInstanceState()(3)。
通常來(lái)說(shuō),跳轉(zhuǎn)到其他的activity或者是點(diǎn)擊Home都會(huì)導(dǎo)致當(dāng)前的Activity執(zhí)行onSaveInstanceState,因?yàn)檫@種情況下的Activity都是有可能會(huì)被Destory并且是需要保存狀態(tài)以便后續(xù)恢復(fù)使用的,而從跳轉(zhuǎn)的Activity點(diǎn)擊Back回到前一個(gè)Activity,那么跳轉(zhuǎn)前的Activity是執(zhí)行退棧的操作,所以這種情況下是不會(huì)執(zhí)行onSaveInstanceState的,因?yàn)檫@個(gè)Activity不可能存在需要重建的操作。
1、保存Activity狀態(tài)
當(dāng)我們的Activity開始Stop,系統(tǒng)會(huì)調(diào)用 onSaveInstanceState() ,Activity可以用鍵值對(duì)的集合來(lái)保存狀態(tài)信息。這個(gè)方法會(huì)默認(rèn)保存Activity視圖的狀態(tài)信息,如在 EditText 組件中的文本或 RecyclerView 的滑動(dòng)位置。
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
super.onSaveInstanceState(savedInstanceState);
}
注意:我們必須要調(diào)用 onSaveInstanceState() 方法的父類實(shí)現(xiàn),這樣默認(rèn)的父類實(shí)現(xiàn)才能保存視圖狀態(tài)的信息。
2、恢復(fù)Activity狀態(tài)
當(dāng)Activity從Destory中重建,我們可以從系統(tǒng)傳遞的Activity的Bundle中恢復(fù)保存的狀態(tài)。 onCreate() 與 onRestoreInstanceState() 回調(diào)方法都接收到了同樣的Bundle,里面包含了同樣的實(shí)例狀態(tài)信息。
由于 onCreate() 方法會(huì)在第一次創(chuàng)建新的Activity實(shí)例與重新創(chuàng)建之前被Destory的實(shí)例時(shí)都被調(diào)用,我們必須在嘗試讀取 Bundle 對(duì)象前檢測(cè)它是否為null。如果它為null,系統(tǒng)則是創(chuàng)建一個(gè)新的Activity實(shí)例,而不是恢復(fù)之前被Destory的Activity。
下面是一個(gè)示例:演示在onCreate方法里面恢復(fù)一些數(shù)據(jù):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
}
...
}
我們也可以選擇實(shí)現(xiàn) onRestoreInstanceState() ,而不是在onCreate方法里面恢復(fù)數(shù)據(jù)。 onRestoreInstanceState()方法會(huì)在 onStart() 方法之后執(zhí)行,系統(tǒng)僅僅會(huì)在存在需要恢復(fù)的狀態(tài)信息時(shí)才會(huì)調(diào)用 onRestoreInstanceState() ,因此不需要檢查 Bundle 是否為null。
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
注意:與上面保存一樣,總是需要調(diào)用onRestoreInstanceState()方法的父類實(shí)現(xiàn),這樣默認(rèn)的父類實(shí)現(xiàn)才能保存視圖狀態(tài)的信息。
點(diǎn)此進(jìn)入:GitHub開源項(xiàng)目“愛閱”。
感謝優(yōu)秀的你跋山涉水看到了這里,歡迎關(guān)注下讓我們永遠(yuǎn)在一起!