activity生命週期中方法解析

對於activity的生命週期我覺得是一個簡單而又不簡單的問題,很多人可能覺得自己已經很精通了!往往事實卻不以爲然!

要接着討論下面的問題,先來簡單瞭解一下activity,來看一段原文的說明,如下:

 An activity is a single, focused thing that the user can do.  Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with {@link #setContentView}.

上文說的很清楚:activity是一個專注於用戶操作的獨立控件,一般情況下我們的activity都是用於與用戶交互的,而activity通過創建的一個window來實現與用戶的這種關係,在activity中我們通過setContentView來配置這個window所要顯示的內容.

關鍵詞:於用戶交互, 創建window, setContentView配置顯示內容.

首先來看看activity生命週期的流程圖:

相信大家對於上面的流程圖很瞭解,下面我來對上面流程圖中各個方法解析一下;

(1)首先來看看第一個重要的方法,當然也是第一常用的方法:onCreate

 protected void onCreate(Bundle savedInstanceState)

對於activity有以下幾條總結:

  • 在activity的整個生命週期中:onCreate時第一被調用的方法,當然onDestroy是最後一個被調用的方法.
  • onCreate中通常 通過setContentView來配置你的顯示內容,通過findViewById來獲取你想要後面用到的view
  • onCreate經常用來初始化全局需要的數據,比如listview的顯示數據的配置/SharedPreferences保存的數據/savedInstanceState裏面保存的數據等.但是,不是所有需要的數據都在這裏獲取,比如一些耗時的數據獲取(從網絡上獲取大量圖片資源等),你可能需要考慮開闢線程來獲取,畢竟我們不能阻塞主線程.
  • Bundle savedInstanceState裏面保存的值是從什麼地方來:當你的activity調用來onSaveInstanceState之後,你的activity被重啓用時候.所以savedInstanceState保存的數據就是onSaveInstanceState裏面配置的,其目的就是希望能夠從上個被kill的activity實例中恢復回來.因爲onSaveInstanceState的調用一般是個意外,對於什麼樣的意外,後面會講到.
  • 可以在這個方法裏面調用finish()來立即結束這個activity,一旦你這樣做,會立即調用onDestroy,而不會調用生命週期中的其他方法.

(2)onStart

 protected void onStart()

對於onStart有以下幾條總結:

  • 在生命週期中,onStart時緊接着onCreate被調用.之後會調用onResume.另外:當一個activity從新變得可見(後臺狀態)時候:onRestart調用後,onStart也會被調用.
  • onStart調用後,該activity變得可見(處於可見狀態),但是無發和用戶交互(無觸摸事件),還不處於前臺狀態.直到onStop調用時候,該activity在不可見.
  • 所以,在對顯示的ui變化的檢測: 有影響ui顯示的的廣播接收器的註冊檢測/一個lastView顯示內容變化的檢測(setOnEditorActionListener)等都在這裏註冊,當然記得在onStop取消註冊.舉一個例子:一個飛行模式切換的界面.切換飛行模式是一個switch的按鈕,在來回點擊switch的時候,會去設置飛行模式(開啓/關閉),同時將這個swith按鈕配置爲不可用狀態,等飛行模式切換成功時候,纔會設置這個switch按鈕位可以操作狀態,這裏如何知道飛行模式切換成功呢?辦法就是在onStart裏面配置一檢測飛行模式狀態改變的檢測器.

(3)onResume

 protected void onResume()

對於onResume有以下幾條總結:

  • onResume調用以後,這個activity就成爲來(foreground lifetime)前臺activity.這個狀態一隻持續到onPause被調用.所以activity每一次進入前臺狀態的時候都要調onResume.
  • onResume被調用就標識這個actovity可以與使用者交互(交流).
  • 需要注意的是:這個地方被調用以後並不能確保這個activity對於使用者來說時可見的.因爲一些系統級的窗口可能會覆蓋在這個activity之上(比如:鎖屏界面).要知道當前的activity是否可見可以通過覆蓋這個方法onWindowFocusChanged(boolean hasFocus)來獲知.
  • onResume中通常可以啓動一些需要的動畫效果,獲知對於一些需要的設備的開啓(比如:camera)

(4)onPause

 protected void onPause()

對於onPause有以下幾條總結:
  • 當activity從前臺變成後臺狀態時候會立即調用.
  • 當從當前的activity(A_activity)啓動另外一個activity(B_activity)時候,當前的activity會立即調用自己的onPause,並且等這個onPause返回後(執行完),activity(B_activity)纔會被創建.所以,onPause的執行事件儘量不要太長.
  • onPause裏面通常用來保存activity狀態的數據,一般來說時一些activity顯示狀態的一些簡單的數據(SharedPreferences)保存.此外還用來停止正在播放的動畫.以及釋放耗cpu等其他設備資源的操作(暫停一些不需要的線程/釋放不需要的設備camera等),其主要目的是使其可以儘快啓動下一個activity.
  • onPause之後,onStop一般會被調用,當然偶爾也不會調用onStop.
  • 我們知道,不處於前臺狀態的activity是可能被kill的.這個時候onSaveInstanceState會被調用,這個地方用來保存數據,以便下次能夠恢復這個被調用過的又被意外kill掉的activity. 這裏保存的數據和上面的石油差別的:onSaveInstanceState中通常保存的數據相對於application來說時全局的,而不是僅僅使用於這個actovity的.比如content providers等.

(5)onStop

 protected void onStop()

對於onStop有以下幾條總結:
  • 當變成後臺狀態時候,變得不可見時onPause就會被調用.
  • 這個方法是可能永遠不被調用的.當memory不夠時候,需要kill掉這個activity.

(6)onDestroy

 protected void onDestroy()

對於onDestroy有以下幾條總結:
  • 不能試圖在onDestroy中保存數據.
  • 一般在onDestroy中釋放一些activity自己無法釋放的資源,比如你開闢的一些線程/Receiver以及Service的停止等.
  • 在onDestroy中你可以通過isFinishing()來判斷是主動通過調用finish來kill這個activity還是意外android因爲資源經常等原因kill的.


最後看看activity中的其他幾個重要方法:

  • onSaveInstanceState

protected void onSaveInstanceState(Bundle outState)

這個方法的目的是:在一個activity被系統kill之前,來保存這個activity實例的一些狀態到這個Bundle裏面,以便在這個activity再次啓動的時候調用onCreate和onRestoreInstanceState來獲取之前的保存的狀態.

對於onSaveInstanceState,需要知道以下幾點:

(1)onSaveInstanceState(Bundle outState)不是一個activity被kill就一定會被調用的. 我的理解是:如果系統在因爲某些原因(比如資源緊張)kill這個activity時候,認爲這個activity是會被再次使用的時候就會調用onSaveInstanceState來保存數據,以便下次啓用時候可以使用.

這一點理解起來比較複雜,來看看原文給的一個例子:如果activity B的啓動在activity A的上面(就是說當activity B中按返回按鍵時候就回到activity A),可能在系統資源緊張的時候activity A會被系統給kill掉!這個時候,系統就會認爲用戶此時kill掉的這個activity A是會被調用的,因爲只要用戶點擊返回按鍵就會調用的activity A.所以這種情況下在kill掉activity A的時候就會回調activity A的onSaveInstanceState.這樣就能保證即便是在activity A被kill過,但是返回後仍然顯示着原來 的樣子.

第二個例子:就是我們經常遇到的橫豎屏的切換,我們知道這個時候activity是會首先被kill的,在這種情況onSaveInstanceState時會被調用的,道理很上面一樣:系統認爲當前kill掉的activity是會再次重複使用的!

(2)onSaveInstanceState和生命週期中的其他方法是不一樣的,比如onPause/onStop等! 其主要原因就是onSaveInstanceState不能確定每次kill掉一個activity都被調用.比如上面的activity AB例子:當按返回按鍵時候,推出activity B時候,在kill這個activity B時候,就不會調用activity B的onSaveInstanceState.因爲系統認爲這是一個暫時不需要重複使用的activity.這種情況下,activity B的onPause/onStop等生命週期的方法卻是會調用的.

(3)onSaveInstanceState調用的時機. 當一個activity被kill掉之前纔有可能調用,並且在activity的onStop之後調用,但是不確定是onPause之前/之後調用.下面時原文說明:

   If called, this method will occur before {@link #onStop}.  There are no guarantees about whether it will occur before or after {@link #onPause}.

  • onNewIntent

protected void onNewIntent(Intent intent)

onNewIntent調用時機:

       當通過startActivity方式啓動一個activity時,並且啓動模式是:"singleTop".或者從新啓動一個以及處於statck的頂部的activity時

onNewIntent調用後的intent變化:

      onNewIntent調用後,通過getIntent獲取的intent卻是以前調用activity的intent,如果要更新intent,你需要在onNewIntent通過調用setIntent來更改爲這次啓動activity的intent.


  • onWindowFocusChanged

public void onWindowFocusChanged(boolean hasFocus)

     從方法名可以知道這個方法是在當前這個activity的window獲得或者取消焦點時候調用的,該方法可以確定當前的activity是否可見.實際上onResume也有類似的作用,不過是有差別的:我們知道activity之所以可以顯示內容,是因爲其中的window,onResume其實只是針對當前的activity的window,也就是說onResume時activity級的;而onWindowFocusChanged很顯然不僅僅是針對activity的window,而是所有的window. 也就是說:就算一個activity處於onResume狀態,也有可能其他的非activity的window可能覆蓋他而獲得焦點.比如popup窗口,dialog窗口,鎖屏等. 還需要注意的是:一般情況不用擔心onWindowFocusChanged不會被調用到.

  • onAttachedToWindow

public void onAttachedToWindow()

     與view中的onAttachedToWindow類似:噹噹前activity的window加入到window manager時候,一個window在顯示前時需要加入到window manager,所以一個activity的window顯示前會調用這個方法onAttachedToWindow.並且在onResume之後調用.

     onAttachedToWindow中通常用來配置當前window的一些屬性,比如當需要當前activity獲得HOMEKEY事件時候,可以在這個方法裏面設置: getWindow().addFlags(FLAG_HOMEKEY_DISPATCHED); 很顯然,在調用 onAttachedToWindow的時候這個activity的window以及初始化了.實際上可以做更多的事情,比如在PlatLogoActivity中裏面, 其顯示的內容都是在onAttachedToWindow裏面創建的:包括顯示的view的創建和初始化, view動畫的初始化等.

  • onDetachedFromWindow

protected void onDetachedFromWindow()

     和上面的onAttachedToWindow相反,只是調用的時機是在onDestroy之後.


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