學習Activity
生命週期,首先咱們要明白,學習它的目的不只在於要知道有哪些生命週期,而是在於明白各回掉函數調用的時機,以便在合適的時機進行正確的操做,如初始化變量、頁面展現、數據操做、資源回收等。平時的工做習慣都是,onCreate(xxx)
初始化,onResume()
註冊、拉取數據,onPause()
反註冊,onDestroy()
釋放資源,這篇文章總結了一些和關鍵生命週期相關聯的一些要點。java
Activity
的生命週期理解成爲一個金字塔模型,它是基於下面兩點:
Activity
所處的狀態**這個模型中包含了Activity
的六種狀態:bash
Created
:建立完成Started
:可見Resumed
:可見Paused
:部分可見Stopped
:不可見Destroyed
:銷燬在這六種狀態當中,只有Resumed
、Paused
、Stopped
這幾種狀態在用戶沒有進一步操做時會保持在該狀態,而其他的,都會在執行完相應的回調函數後快速跳過。ide
protected void onCreate(Bundle savedInstanceState)
Activity
被建立了。Activity
實體對象當中,全部的東西都是未初始化的,咱們通常須要作的事情包括調用setContentView
方法設置該Activity
的佈局,初始化類成員變量。onCreate(xxx)
方法執行完以後,Activity
就進入了Created
狀態,然而它並不會在這個狀態停留,系統會接着回調onStart()
方法由Created
狀態進入到Started
狀態。onCreate(xxxx)
是全部這些回調方法中惟一有參的,該參數保存了上次因爲Activity
被動回收時所保存的數據。protected void onStart()
onStart()
方法執行完後,Activity
就進入了Started
狀態,它也一樣不會在該狀態停留,而是接着回調 onResume()
方法進入Resumed
狀態。onStart()
被回調的狀況有兩種:Created
狀態過來Stopped
狀態過來,從這種狀態過來還會先通過onRestart()
方法。Stopped
狀態跳轉過來,所以若是咱們在onStop()
當中反註冊了一些廣播,或者釋放了一些資源,那麼在這裏須要從新註冊或者初始化,能夠認爲,onStart()
和onStop()
是成對的關係。Created
和Started
都不是持久性的狀態,那麼爲何要提供一個onStart()
回調給開發者呢,直接由Created
狀態或者是 Stopped
狀態通過onResume()
這條路走到Resumed
狀態不就能夠嗎,那麼咱們就要分析一下從 onCreate()
到onStart()
,再到onResume()
的過程當中,作了哪些其它的操做,這有利於咱們在平時的開發中區分這兩個回調的使用場景,咱們來看一下源碼。首先咱們看一下onStart()
方法調用的地方,經過下面這段代碼,咱們能夠知道Activity
的onStart()
最初是經過Activity#performStart()
方法調用過來的:函數
<!-- Activity.java -->
private Instrumentaion mInstrumentation;
final void performStart() {
mInstrumentation.callActivityOnStart(this);
}
<!-- Instrumentaion.java -->
public void callActivityOnStart(Activity activity) {
activity.onStart();
}
複製代碼
而Activity#performStart()
方法是由ActivityThread#performLaunchActivity(
調過來的:佈局
<!-- ActivityThread.java -->
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity a = performLaunchActivity(r, customIntent); //performCreate, performStart()
if (a != null) {
....
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed); //performResume()
....
}
}
//首先看一下調用performCreate, performStart的地方。
private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
mInstrumentation.callActivityOnCreate(activity, r.state); //performCreate
....
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); //1.onRestoreIntanceState()
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
mInstrumentation.callActivityOnPostCreate(activity, r.state); //2.onPostCreate
if (!activity.mCalled) {
throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onPostCreate()");
}
}
...
}
//這是performResume的入口。
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) {
ActivityClientRecord r = performResumeActivity(token, clearHide);
}
//最後看一下performResume真正執行的地方。
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide) {
try {
if (r.pendingIntents != null) {
deliverNewIntents(r, r.pendingIntents); //3.onNewIntent()
r.pendingIntents = null;
}
if (r.pendingResults != null) {
deliverResults(r, r.pendingResults); //4.onActivityResult()
r.pendingResults = null;
}
r.activity.performResume();
}
複製代碼
onStart()
到onResume()
的過程當中,還可能會回調onRestoreInstanceState/onPostCreate/onNewIntent/onActvitiyResult
這幾個方法。onNewIntent
),或者經過startActivityForResult
方法啓動另外一個 Activity
獲得結果返回(onActivityResult
)的時候,在onStart()
方法當中獲得的並非這兩個回調的最新結果,由於上面的這兩個方法並無調用,而在onResume()
當中,這點是能夠獲得保證的。protected void onResume()
Activity
已經徹底可見了,但這個徹底可見的概念並不等同於Activity
所屬的Window
被Attach
了,由於在Activity
初次啓動的時候,Attach
的操做是在回調onResume()
以後的,也就是下面的這段代碼final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) {
....
ActivityClientRecord r = performResumeActivity(token, clearHide);
....
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
WindowManager.LayoutParams l = r.window.getAttributes();
...
wm.addView(decor, l);
}
}
複製代碼
onResume()
方法被回調時,因爲DecorView
並不必定Attach
了,所以這時候咱們獲取佈局內某些View
的寬高獲得的值有多是不正確的,既然onResume()
當中不能保證,那麼onStart()
方法也是同理,全部須要在attachToWindow
以後才能執行或是指望獲得正確結果的操做都須要注意這一點。onResume
當中,咱們通常會作這麼一些事:在可見時從新拉取一些須要及時刷新的數據、註冊 ContentProvider
的監聽,最重要的是在onPause()
中的一些釋放操做要在這裏面恢復回來。protected void onPause()
Activity
部分不可見,例如一個半透明的界面覆蓋在了上面,這時候只要Activity
仍然有一部分可見,那麼它會一直保持在Paused
狀態。Paused
狀態回到Resumed
狀態,只會回調onResume
方法。onPause()
方法中,應該暫停正在進行的頁面操做,例如正在播放的視頻,或者釋放相機這些多媒體資源。onPause()
當中,能夠保存一些必要數據到持久化的存儲,例如正在編寫的信息草稿。onPause()
方法,因此若是進行了耗時的操做,那麼會影響到新界面的啓動時間,官方文檔的建議是這些操做應該放到 onStop()
當中去作,其實在onStop()
中也不該當作耗時的操做,由於它也是在主線程當中的,而在主線程中永遠不該該進行耗時的操做。GPS
)、以及一些僅當頁面得到焦點時才須要的資源。Paused
狀態時,Activity
的實例是被保存在內存中的,所以在其從新回到Resumed
狀態的過程當中,不須要從新初始化任何的組件。protected void onStop()
Activity
已經徹底不可見了。onPause()
,以後再回調onStop()
。onStop()
執行完以後,系統有可能會銷燬這個Activity
實例,在某些極端狀況下,有可能不會回調onDestroy()
方法,所以,咱們須要在onStop()
當中釋放掉一些資源來避免內存泄漏,而 onDestory()
中須要釋放的是和Activity
相關的資源,如線程之類的(這點平時在工做中不多用,通常咱們都是在onDestroy()
中釋放全部資源,並且也沒有去實現onStart()
方法,究竟何時不會走onDestroy()
,這點值得研究,目前的猜想是該Activity
在別的地方被引用了,致使其不能回收)。Activity
從Stopped
狀態回到前臺時,會先回調onRestart()
方法,然而咱們更多的是使用onStart()
方法做爲onStop()
的對應關係,由於不管是從Stopped
狀態,仍是從Created
狀態跳轉到Resumed
狀態,都是須要初始化必要的資源的,而它們通過的共同路徑是onStart()
。protected void onDestroy()
Activity
是真正要被銷燬了,