Activity各種情況下的生命週期

Situation1

正常啓動: onCreate()  →   onStart()  →  onResume();

返回健退出: onPause()  →   onStop()  →   onDestory();

 

Situation2:

正常啓動 : onCreate()  →   onStart   →  () onResume();

按home健: onPause()  →   onStop();

正常啓動:onRestart()  →   onStart()   →  onResume();

 

Situation3:

正常啓動:onCreate()   →   onStart()   →   onResume();

橫豎屏切換: onPause()  →   onStop()   →  onDestory()   →   onCreate()   →  onStart()  →   onResume();

 

Situation4:

前提條件:Activity的AndroidManifest.xml中設置android:configChanges="orientation|keyboardHidden|screenSize”

正常啓動:onCreate()   →   onStart()   →  onResume();

橫豎屏切換: onConfigurationChanged();

 

結論:

設置Activity的android:configChanges="orientation |keyboardHidden|screenSize"時,切 屏不會重新調用各個生命週期,只會執 行onConfigurationChanged方法;

自從Android3.2(API13), 在設置Activity的 android:configChanges="orientation |keyboardHidden"後,還是一樣會重新 調用各個生命週期的。因爲screensize 也開始跟着設備的橫豎切換而改變。所以,在AndroidManifest.xml裏設置的 MiniSdkVersion和TargetSdkVersion屬性大於等於13的情況下,如果你想阻止程序在運行時重新加載Activity,除了 設置"orientation",你還必須設 置"ScreenSize"。

 

一:典型情況下的生命週期分析
1.先上一個非常經典的圖: 
 
不同於其他編程範式(程序從main()方法開始啓動),Android系統根據生命週期的不同階段喚起對應的回調函數來執行代碼。系統存在啓動與銷燬一個activity的一套有序的回調函數。下面就簡要分析一下各個過程的回調函數。

(1)onCreate方法,Activity被啓動時的第一個方法,表示Activity正在被創建,在這個方法中一般做一些初始化的工作,比如調用setContentView方法加載界面佈局,並且可以做一些初始化數據的工作:聲明UI元素,定義成員變量,配置UI等。 
Note:onCreate儘量少做一些不必要的操作,避免Activity啓動太久,使用戶半天看不到Activity

(2)onStart方法,表示Activity正在被啓動,其實這時Activity已經可見了,正如上圖所表示的Visible,但並不能被用戶所見,我們可以這樣理解,Activity現在運行到了後臺,還沒有準備好到前臺和用戶交互。

(3)onResume方法,此時Activity來到前臺和用戶進行交互,用戶真正的看到了Activity. 
Note:往往程序在onCreate執行完成之後會迅速調用onStart方法和onResume方法。

(4)onPause方法,表示Activity正在停止,該狀態下,activity的部分被另外一個activity所遮蓋:另外的activity來到前臺,但是半透明的,不會覆蓋整個屏幕。被暫停的activity不再接受用戶的輸入且不再執行任何代碼。

(5)onStop方法,該狀態下, activity完全被隱藏,對用戶不可見。可以認爲是在後臺。當stopped, activity實例與它的所有狀態信息(如成員變量等)都會被保留,但activity不能執行任何代碼。 
Note:整個生命週期方法中,只有onResume,onPause,onStop方法是“靜態”的,既可以存在較長的時間的。其它狀態 (Created與Started)都是短暫的,系統快速的執行那些回調函數並通過執行下一階段的回調函數移動到下一個狀態。也就是說,在系統調用onCreate(), 之後會迅速調用onStart(), 之後再迅速執行onResume()。。

(6)onRestart方法,Activity從不可見又變爲可見時會調用。此時調用順序爲:onRestart -> onStart -> onResume

(7)onDestroy方法:表示Activity即將被銷燬,當收到需要將該activity徹底移除的信號時,系統會調用這個方法。 
Note:大多數 app並不需要實現這個方法,因爲局部類的references會隨着activity的銷燬而銷燬,並且我們的activity應該在onPause()與onStop()中執行清除activity資源的操作。然而,如果activity含有在onCreate調用時創建的後臺線程,或者是其他有可能導致內存泄漏的資源,則應該在OnDestroy()時進行資源清理,殺死後臺線程。 
Note: 除非程序在onCreate()方法裏面就調用了finish()方法,系統通常是在執行了onPause()與onStop() 之後再調用onDestroy() 。在某些情況下,例如我們的activity只是做了一個臨時的邏輯跳轉的功能,它只是用來決定跳轉到哪一個activity,這樣的話,需要在onCreate裏面調用finish方法,這樣系統會直接調用onDestory,跳過生命週期中的其他方法。 
Note:至於爲什麼當我們的activity只是做了一個臨時的邏輯跳轉的功能,決定跳轉到哪一個activity,需要在onCreate裏面調用finish方法,我的理解是,因爲當從Activity a跳轉到Activity b時,a的onPause方法執行過後,b的onResume方法纔會執行,如果不在a的onCreate方法中finish(),啓動b可能會很費時,所以我們寧可在onStop做一些操作也不要在onPause中做,並且完全沒必要不finish().,並且此時注意在a的onDestroy做資源回收工作,避免造成內存泄露

二:異常情況下的生命週期分析
(1)情況一:資源相關的系統配置發生改變導致Activity被殺死並重新創建 
當系統配置發生改變後,如從橫屏手機切換到了豎屏,Activity會被銷燬,其onPause,onStop,onDestroy方法均會被調用,同時由於是在異常情況下被終止的,系統會調用onSavedInstanceState來保存當前Activity的狀態(正常情況下不會調用此方法),這個方法的調用時機是在onStop之前,當Activity重新被創建後,系統調用會調用

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }
方法,並且把Activity銷燬時onSavedInstanceState方法所保存的Bundle對象作爲參數同時傳遞給onRestoreInstanceState和onCreate方法,onRestoreInstanceState是在onStart之後調用。 
Note:我們知道,當Activity被異常終止後被恢復時,系統會自動的幫我們恢復數據和一些狀態,如文本框用戶輸入的數據,listview的滾動位置等,關於保存和恢復View的層次結構和數據,系統的工作流程是這樣的,首先Activity被意外終止時,Activity會調用onSavedInstanceState去保存數據,然後Activity會委託Window去保存數據,接着Window再委託它上面的頂級容器去保存數據,頂層容器是一個ViewGroup,一般來說它很可能是一個DecorView.最後頂層容器再去一一通知它的子元素來保存數據,這樣整個數據保存過程就完成了,可以發現,這是一種典型的委託思想,上層委託下層,父容器委託子容器去處理一些事情。

(2)情況二:資源內存不足導致低優先級的Activity被殺死 
Activity按照優先級我們可以分爲以下的三種: 
a.前臺Activity—正在和用戶交互的Activity,優先級最高。 
b.可見但非前臺Activity,如處於onPause狀態的Activity,Activity中彈出了一個對話框,導致Activity可見但是位於後臺無法和用戶直接交互。 
c.後臺Activity—已經被暫停的Activity,比如執行了onStop方法,優先級最低。 
當系統內存不足時,系統就會按照上述的優先級順序選擇殺死Activity所在的進程,並在後續通過onSaveInstanceState緩存數據和onRestoreInstanceState恢復數據。 
Note:如果一個進程中沒有四大組件在執行,那麼這個進程將很快被殺死,因此,一些後臺工作不適合脫離了四大組件工作,比較好的方法是將後臺工作放入Service中從而保證進程有一定的優先級,這樣就不會輕易的被系統殺死。 
Note:系統只恢復那些被開發者指定過id的控件,如果沒有爲控件指定id,則系統就無法恢復了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章