Activity 知識梳理(1) Activity生命週期

1、概述

學習Activity生命週期,首先咱們要明白,學習它的目的不只在於要知道有哪些生命週期,而是在於明白各回掉函數調用的時機,以便在合適的時機進行正確的操做,如初始化變量、頁面展現、數據操做、資源回收等。平時的工做習慣都是,onCreate(xxx)初始化,onResume()註冊、拉取數據,onPause()反註冊,onDestroy()釋放資源,這篇文章總結了一些和關鍵生命週期相關聯的一些要點。java

2、金字塔模型

Activity 生命週期金字塔模型.png
在官方文檔中,把 Activity的生命週期理解成爲一個金字塔模型,它是基於下面兩點:

  • 金字塔的每一個階梯表示**Activity所處的狀態**
  • 回調函數則是各狀態轉換過程中所通過的路徑

這個模型中包含了Activity的六種狀態:bash

  • Created:建立完成
  • Started:可見
  • Resumed:可見
  • Paused:部分可見
  • Stopped:不可見
  • Destroyed:銷燬

在這六種狀態當中,只有ResumedPausedStopped這幾種狀態在用戶沒有進一步操做時會保持在該狀態,而其他的,都會在執行完相應的回調函數後快速跳過。ide

3、關鍵生命週期

3.1 protected void onCreate(Bundle savedInstanceState)

  • 該方法被回調時,意味着一個新的Activity被建立了。
  • 因爲當前處於一個新的Activity實體對象當中,全部的東西都是未初始化的,咱們通常須要作的事情包括調用setContentView方法設置該Activity的佈局,初始化類成員變量。
  • onCreate(xxx)方法執行完以後,Activity就進入了Created狀態,然而它並不會在這個狀態停留,系統會接着回調onStart() 方法由Created狀態進入到Started狀態。
  • 注意到,onCreate(xxxx)是全部這些回調方法中惟一有參的,該參數保存了上次因爲Activity被動回收時所保存的數據。

3.2 protected void onStart()

  • onStart()方法執行完後,Activity就進入了Started狀態,它也一樣不會在該狀態停留,而是接着回調 onResume()方法進入Resumed狀態。
  • onStart()被回調的狀況有兩種:
  • Created狀態過來
  • Stopped狀態過來,從這種狀態過來還會先通過onRestart()方法。
  • 因爲它也會從Stopped狀態跳轉過來,所以若是咱們在onStop()當中反註冊了一些廣播,或者釋放了一些資源,那麼在這裏須要從新註冊或者初始化,能夠認爲,onStart()onStop()是成對的關係。
  • CreatedStarted都不是持久性的狀態,那麼爲何要提供一個onStart()回調給開發者呢,直接由Created狀態或者是 Stopped狀態通過onResume()這條路走到Resumed狀態不就能夠嗎,那麼咱們就要分析一下從 onCreate()onStart(),再到onResume()的過程當中,作了哪些其它的操做,這有利於咱們在平時的開發中區分這兩個回調的使用場景,咱們來看一下源碼。

首先咱們看一下onStart()方法調用的地方,經過下面這段代碼,咱們能夠知道ActivityonStart()最初是經過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()當中,這點是能夠獲得保證的。

3.3 protected void onResume()

  • 該方法被回調時,意味着Activity已經徹底可見了,但這個徹底可見的概念並不等同於Activity所屬的WindowAttach了,由於在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()中的一些釋放操做要在這裏面恢復回來。

3.4 protected void onPause()

  • 該方法被回調時,意味着Activity部分不可見,例如一個半透明的界面覆蓋在了上面,這時候只要Activity仍然有一部分可見,那麼它會一直保持在Paused狀態。
  • 若是用戶從Paused狀態回到Resumed狀態,只會回調onResume方法。
  • onPause()方法中,應該暫停正在進行的頁面操做,例如正在播放的視頻,或者釋放相機這些多媒體資源。
  • onPause()當中,能夠保存一些必要數據到持久化的存儲,例如正在編寫的信息草稿。
  • 不該該在這裏執行耗時的操做,由於新界面啓動的時候會先回調當前頁面的onPause()方法,因此若是進行了耗時的操做,那麼會影響到新界面的啓動時間,官方文檔的建議是這些操做應該放到 onStop()當中去作,其實在onStop()中也不該當作耗時的操做,由於它也是在主線程當中的,而在主線程中永遠不該該進行耗時的操做。
  • 釋放系統資源,例如先前註冊的廣播、使用的傳感器(如GPS)、以及一些僅當頁面得到焦點時才須要的資源。
  • 當處於Paused狀態時,Activity的實例是被保存在內存中的,所以在其從新回到Resumed狀態的過程當中,不須要從新初始化任何的組件。

3.5 protected void onStop()

  • 該方法被回調時,代表Activity已經徹底不可見了。
  • 在任何場景下,系統都會先回調onPause(),以後再回調onStop()
  • 官方文檔有談到,當onStop()執行完以後,系統有可能會銷燬這個Activity實例,在某些極端狀況下,有可能不會回調onDestroy()方法,所以,咱們須要在onStop()當中釋放掉一些資源來避免內存泄漏,而 onDestory()中須要釋放的是和Activity相關的資源,如線程之類的(這點平時在工做中不多用,通常咱們都是在onDestroy()中釋放全部資源,並且也沒有去實現onStart() 方法,究竟何時不會走onDestroy(),這點值得研究,目前的猜想是該Activity在別的地方被引用了,致使其不能回收)。
  • ActivityStopped狀態回到前臺時,會先回調onRestart()方法,然而咱們更多的是使用onStart() 方法做爲onStop()的對應關係,由於不管是從Stopped狀態,仍是從Created狀態跳轉到Resumed狀態,都是須要初始化必要的資源的,而它們通過的共同路徑是onStart()

3.6 protected void onDestroy()

  • 該方法被回調時,代表Activity是真正要被銷燬了,
  • 此時應當釋放掉全部用到的資源,避免內存泄漏。
相關文章
相關標籤/搜索