Android Activity生命週期

Android生命週期

Android的生命週期:onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy() 以下圖所示:android

  1. 1.當activity啓動時系統會先調用onCreate(),而後調用onStart(),最後調用**onResume()**方法,activity進入運行狀態。
  2. 當activity被別的activity 覆蓋在其上時:系統會掉用onPause(),而後當覆蓋在其上的activity會調用**onCreate() -> onStart() -> onResume()後,第一個activity會調用onStop()**方法使activity暫停。
  3. 當覆蓋在其上的第二個activity關閉返回此activity時,系統會先調用第二個activity的**onPause()方法而後再調用第一個activity的onRestart() -> onStart() -> onResume()方法,進入運行狀態,此時第二個activity才調用onStop() -> onDestroy()**方法關閉。
  4. 用戶退出當前activity:系統先調用onPause(),而後調用onSotp(),最後調用**onDestroy()**方法,結束當前activity。

以下日誌打印 第一個activity MainActivity 打開 SingleTopActivity 在返回到 MainActivitygit

MainActivity :onPause 方法-------------------------
     SingleTopActivity :onCreate 方法-------------------------
     SingleTopActivity :onStart 方法-------------------------
     SingleTopActivity :onResume 方法-------------------------
     MainActivity :onSaveInstanceState 方法--------------------
     MainActivity :onStop 方法-------------------------
     SingleTopActivity :onPause 方法-------------------------
     MainActivity :onRestart 方法-------------------------
     MainActivity :onStart 方法-------------------------
     MainActivity :onResume 方法-------------------------
     SingleTopActivity :onStop 方法-------------------------
     SingleTopActivity :onDestroy 方法-------------------------
複製代碼
  • onRestart():表示activity正在從新啓動,通常狀況下是當前activity從不可見從新變成可見狀態時,**onRestart()**就會被調用,這種狀況通常是用戶行爲致使的,如從其餘頁面返回當前頁面時,或者用戶按home鍵切換到桌面在從新打開app。github

  • onStart()和onStop():onStart()表示activity可見了,可是尚未獲取焦點,沒法進行交互。onStop()是和onStart()對應的當activity從可見轉不可見是調用。app

  • onResume()和onPause():onResume()表示activity已經獲取焦點了,能夠進行交互了,onPause()是和onResume()方法對應的表示當前activity失去了焦點,此時能夠作一些存儲數據和中止動畫等工做,可是不能太好時,不是會影響到新的activity的顯示,由於只有onPause()執行完了,新的activity纔會進入 onCreate() 等方法。ide

  • onDestroy():onDestroy()表示activity正在銷燬,通常咱們是在這進行資源的釋放,以免內存的泄漏。動畫

注意:this

- 若是覆蓋在其上的activity的風格是dialog風格的化,此activity是不會進入**onSotp()**方法,回到此activity時也**不會調用onRestart()和onStart()方法** 會直接調用**onResume()**方法。

- 若是activity中彈出dialog對話框的時候,**activity是不會調用onPause()方法**;

- 只有舊的activity onPause()方法執行完後,新的activity才啓動
- 在因此狀況下,系統在調用了onPause()和onStop()以後都會調用onDestroy(),只有一個例外:當你從onCreate()方法類調用了finish()時,在這種狀況下,系統會馬上調用onDestroy(),而不調用任何其餘生命週期方法。日誌以下:
複製代碼
MainActivity :onPause 方法-------------------------
 DialogActivity :onCreate 方法-------------------------
 MainActivity :onResume 方法-------------------------
 DialogActivity :onDestroy 方法-------------------------
複製代碼

異常狀況下的生命週期:好比系統資源配置發生改變以及系統內存不足時,activity就可能被殺死。spa

  • 狀況1:資源相關配置方式改變致使activity被殺死並從新建立。 好比當前activity處於豎屏,旋轉屏幕,這時因爲activity的系統配置改成了橫屏狀態,在默認狀況下,activity就會被銷燬而且從新建立,日誌打印以下:
MainActivity :onCreate 方法-------------------------
 MainActivity :onCreate:MainActivity  TaskId:130  hasCode:151566767
 MainActivity :onStart 方法-------------------------
 MainActivity :onResume 方法-------------------------
 MainActivity :onPause 方法-------------------------
 MainActivity :onSaveInstanceState 方法-------------------------
 MainActivity :onStop 方法-------------------------
 MainActivity :onDestroy 方法-------------------------
 MainActivity :onCreate 方法-------------------------
 MainActivity :onCreate:MainActivity  TaskId:130  hasCode:233659052
 MainActivity :onStart 方法-------------------------
 MainActivity :onRestoreInstanceState 方法-------------------------
 MainActivity :onResume 方法-------------------------
 MainActivity :onPause 方法-------------------------
 MainActivity :onSaveInstanceState 方法-------------------------
 MainActivity :onStop 方法-------------------------
 MainActivity :onDestroy 方法-------------------------
 MainActivity :onCreate 方法-------------------------
 MainActivity :onCreate:MainActivity  TaskId:130  hasCode:262962597
 MainActivity:TaskAffinity:com.hugo.reviewbasic
 MainActivity :onStart 方法-------------------------
 MainActivity :onRestoreInstanceState 方法-------------------------
 MainActivity :onResume 方法-------------------------
複製代碼

在上面這日誌中 咱們進入MainActivity -> onCreate() -> onStart () -> onResume() 這個時候MainActivity已經在棧頂並得到焦點了,而後咱們旋轉手機屏幕,3d

這時調用了 onPause() -> onSaveInstanceState() -> onStop() - onDestroy() 方法把當前MainActivity 銷燬了,而後緊接着又從新建立了一個MainActivity -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()日誌

這是MainActivity已經從新建立而且是橫屏顯示的,這是咱們又旋轉手機屏幕從新豎屏顯示 ,這是調用了 onPause() -> onSaveInstanceState() -> onStop() - onDestroy() 方法把當前橫屏MainActivity 銷燬了,並從新建立了豎屏的MainActivity -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()

在這上面的流程咱們能夠看到 在第一次進入MainActivity 時是每有調用onRestoreInstanceState() 方法的而是在從新建立時才調用了該方法,這個方法是用來作什麼的呢?這個方法就是用來在activity被銷燬並從新建立時用來恢復咱們保存的數據用的,那咱們的數據在哪保存的呢,能夠看到日誌裏每次在銷燬前都有調用 onSaveInstanceState() 方法,這個方法就是用來保存數據用的。

在onSaveInstanceState()方法中系統會傳入Bundle對象用來存儲數據,在從新建立時onRestoreInstanceState()方法系統會傳入在onSaveInstanceState()方法是存儲了數據的Bundle對象,在onRestoreInstanceState()方法裏能夠在傳入的Bundle對象中獲取存儲的數據進行頁面恢復。

根據日誌能夠看出 onSaveInstanceState() 老是在 onStop()以前調用,而onRestoreInstanceState() 老是在onStart() 以後調用,並且onRestoreInstanceState()在activity第一次建立時是不會調用的。

  • 狀況2:在資源不足的狀況下致使低優先級的activity被殺死。 這種狀況下和前面第一種狀況1的數據存儲和恢復是徹底一致的,activity按照優先級從高到低能夠分爲如下三種:

    1. 前臺activity:正在和用戶交互的activity,優先級最高。 2.可見可是非前臺activity:就是能看見,可是沒有獲取到焦點不能和用戶進行直接交互。 3.後臺activity:已經被暫停的activity,好比執行了onStop()方法,優先級最低。

注意: 必須始終調用 onSaveInstanceState()和onRestoreInstanceState() 的超類實現由於這兩個方法默認實現了保存有關activity視圖層次的狀態信息和恢復視圖層次結構狀態,列如EditText小部件的文本或ListView的滾動位置。並且全部的View都有onSaveInstanceState()和onRestoreInstanceState()這兩個方法。


自行處理配置變動: 咱們能夠在聲明Activity將自行處理配置變動,這樣就能夠阻止系統重啓activity了。 聲明時在AndroidManifest.xml文件中編輯相應的""元素,設置以包含的 android:configChanges 屬性(最經常使用的值包括「orientation」和「keyboardHidden」,分別用於避免因屏幕方向和可用鍵盤改變而致使的重啓)。咱們能夠在該屬性中聲明多個匹配值,方法是用「 | 」字符分隔這些配置值。 以下配置:

<activity android:name=".singletop.OtherTopActiivty" android:configChanges="orientation|screenSize" android:launchMode="singleTop"/>
複製代碼

如今,當其中一個配置發生改變是OtherTopActiivty不會重啓,可是OtherTopActiivty的onConfigurationChanged()方法會被調用,系統會 傳入Configuration對象指定新的設備配置。咱們能夠經過讀Configuration中的字段,來肯定新配置,進行相應的UI更改。 如下是在onConfigurationChanged()實現檢查當前設備的方向:

override fun onConfigurationChanged(newConfig: Configuration?) {   
super.onConfigurationChanged(newConfig)  
LogUtil.i(TAG,"$ActivityName :onConfigurationChanged 方法-------------------------"if(newConfig?.orientation == Configuration.ORIENTATION_LANDSCAPE){     
LogUtil.i(TAG,"$ActivityName :onConfigurationChanged 橫屏")  
Toast.makeText(this,"橫屏",Toast.LENGTH_SHORT).show()  
}else if(newConfig?.orientation == Configuration.ORIENTATION_PORTRAIT){    
LogUtil.i(TAG,"$ActivityName :onConfigurationChanged 豎屏")   
Toast.makeText(this,"豎屏",Toast.LENGTH_SHORT).show() 
}
}


複製代碼

注意:

  • 自行處理配置變動可能致使備用資源的使用更爲困難,由於系統不會自動應用這些資源。因此只有在咱們必須避免activity因配置改變而重啓這種狀況下,才考慮採用自行處理配置變動這種方法,並且對於大多數應用並不建議使用此方法。
    複製代碼
  • 在Android3.0(API 級別13)開始,設備在縱向和橫向之間切換時,「屏幕尺寸」也會發生改變,所以在開發針對API級別13或更高版本的應用時,若要避免因爲設備方向的改變而致使運行時重啓,則除了「orientation」值外,還必須添加「screenSize「值。也就是必須聲明android:configChanges="orientation|screenSize"。
    複製代碼
  • 在聲明有Activity處理配置變動時,咱們有責任要爲其提供備用資源的全部元素。如聲明瞭activity處理方向變動,有些圖像是應該橫向和縱向之間切換,則必須在 onConfigurationChanged()方法中將每一個資源從新分配給每一個元素。
    複製代碼

這個例子代碼在這裏

相關文章
相關標籤/搜索