Android基礎 - activity生命週期

1.生命週期

生命週期如下如圖所示:

1.1生命週期示意圖

1.1 典型生命週期分析:

在正常情況下,生命週期爲如下經歷:

  • onCreate():Activity正在被創建,在這個方法中可以做一些初始化工作,比如調用setContentView去加載佈局資源、初始化Activity所需要的資源等。

  • onRestart():Activity正在重新啓動,一般情況下,在當前activity由不可見變爲可見的時候調用該方法。這種情況一般由用戶行爲所致。

  • onStart():activity正在被啓動,即將開始,這時候activity可見但不在前臺,用戶無法操作。可以理解爲activity已經顯示了但是我們還看不到。

  • onResume() : 此時activity已經可見,並且可以交互。和onStart()方法的區別在於onStart()時activity還在後臺,不能交互。

  • onPause(): activity正在停止,正常情況下onStop會被接着調用。如果在這個時候快速返回當前activity則會直接調用onResume()。但是這種情況一般很難實現。

  • onStop(): activity即將停止,可以做一些重量級的回收工作但是不能做耗時操作。

  • onDestriy(): activity即將被銷燬。

具體實例如下:(使用kotlin實現)

class MainActivity : AppCompatActivity() {
    val TAG : String = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        LogUtils.d("onCreate")
    }
    override fun onPause() {
        super.onPause()
        LogUtils.d("onPause")
    }
    override fun onDestroy() {
        super.onDestroy()
        LogUtils.d("onDestroy")
    }
    override fun onStart() {
        super.onStart()
        LogUtils.d("onStart")
    }
    override fun onResume() {
        super.onResume()
        LogUtils.d("onResume")
    }

    override fun onStop() {
        super.onStop()
        LogUtils.d("onCreate")
    }
    override fun onRestart() {
        super.onRestart()
        LogUtils.d("onRestart")
    }
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        LogUtils.d("onNewIntent")
    }
}

1.1.1 正常情況下生命週期方法回調情況如下:

  • 一般情況下啓動新的activity的生命週期方法執行順序爲:

onCreate() -> onStart() -> onRessume()

  • 當用戶打開新的activity或切換到桌面的時候,回調順序爲:

onPause() -> onStop()
此時存在特殊情況:當啓動的activity主題爲透明,則當前activity不會回調onStop()方法。

  • 當用戶再次回到原Activity時。,回調如下:

onRestart() -> onStart() -> onResume()

  • 當用戶按返回鍵回退時,回調如下:

onPause() -> onStop() -> onDestroy()

1.1.1.1 啓動新的activity時的生命週期
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        LogUtils.d("onCreate")
        // 跳轉到第二個頁面
        btn2activity.setOnClickListener {
            var sIntent = Intent()
            sIntent.setClass(MainActivity@this,SecondActivity::class.java)
            startActivity(sIntent)
        }
    }

第二個頁面:

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        LogUtils.d("onCreate")
    }
    override fun onPause() {
        super.onPause()
        LogUtils.d("onPause")

    }

    override fun onDestroy() {
        super.onDestroy()
        LogUtils.d("onDestroy")

    }

    override fun onStart() {
        super.onStart()
        LogUtils.d("onStart")

    }

    override fun onResume() {
        super.onResume()
        LogUtils.d("onResume")

    }

    override fun onStop() {
        super.onStop()
        LogUtils.d("onCreate")

    }

    override fun onRestart() {
        super.onRestart()
        LogUtils.d("onRestart")

    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        LogUtils.d("onNewIntent")

    }

生命週期日誌爲:

2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onPause(MainActivity.kt:26)
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onPause
2019-02-16 15:08:23.340 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.429 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ SecondActivity.onCreate(SecondActivity.kt:15)
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onCreate
2019-02-16 15:08:23.430 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.431 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.431 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ SecondActivity.onStart(SecondActivity.kt:31)
2019-02-16 15:08:23.431 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.432 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStart
2019-02-16 15:08:23.432 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ SecondActivity.onResume(SecondActivity.kt:37)
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onResume
2019-02-16 15:08:23.435 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.803 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onStop(MainActivity.kt:50)
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStop
2019-02-16 15:08:23.805 29929-29929/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════

1.1.2 異常情況下生命週期分析

1. 資源相關的系統配置發生改變導致Activity被殺死並重啓

異常情況下Activity的重建過程

當系統配置發生變化後(例如默認情況下的橫豎屏切換),activity會被銷燬,onPause、onStop、onDestroy方法均會被調用,同時,activity是在異常情況下被銷燬,所以還會調用activity的onSaveInstanceState方法,保存當前activity的狀態。這個方法調用是在onStop之前,它和onPause沒有順序關係。這個方法的調用只是在異常情況下,正常情況下不會調用。當activity被重新創建之後,系統會調用onRestroeInstanceState方法,並且將activity銷燬時onSaveInstanceState方法保存的Bundle對象最爲參數同時傳遞給onRestroeInstanceState和onCreate方法。因此我們可以通過onRestroeInstanceState和onCreate方法來判斷activity是否被重建,如果被重建,則使用bundle對象的參數恢復。

示例如下:

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        LogUtils.d("onCreate")
        if (savedInstanceState != null) {
            val string = savedInstanceState!!.getString("extra_test")
            LogUtils.d("[onCreate] restroe extra_test == " + string)
        }
     }
override fun onSaveInstanceState(outState: Bundle?) {
        super.onSaveInstanceState(outState)
        LogUtils.d("onSaveInstanceState")
        outState?.putString("extra_test","test")
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
        super.onRestoreInstanceState(savedInstanceState)
        val string = savedInstanceState!!.getString("extra_test")
        LogUtils.d("[onRestoreInstanceState] restroe extra_test == " + string)
    }

橫豎屏切換時的生命週期調用如下:

2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onPause(MainActivity.kt:31)
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onPause
2019-02-16 16:33:46.975 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.976 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onSaveInstanceState(MainActivity.kt:73)
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onSaveInstanceState
2019-02-16 16:33:46.977 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.978 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onStop(MainActivity.kt:55)
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStop
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.979 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onDestroy(MainActivity.kt:37)
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onDestroy
2019-02-16 16:33:46.980 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.055 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onCreate(MainActivity.kt:17)
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onCreate
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onCreate(MainActivity.kt:20)
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ [onCreate] restroe extra_test == test
2019-02-16 16:33:47.056 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.057 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onStart(MainActivity.kt:43)
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onStart
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.058 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onRestoreInstanceState(MainActivity.kt:80)
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ [onRestoreInstanceState] restroe extra_test == test
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.059 3025-3025/com.xyd.activitylaunchmodedemo D/ActivityThread: add activity client record, r= ActivityRecord{76602aa token=android.os.BinderProxy@30b5a73 {com.xyd.activitylaunchmodedemo/com.xyd.activitylaunchmodedemo.MainActivity}} token= android.os.BinderProxy@30b5a73
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➀: ╔══════════════════════════════════════════════════════════════
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➁: ║ MainActivity.onResume(MainActivity.kt:49)
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➂: ╟──────────────────────────────────────────────────────────────
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➃: ║ onResume
2019-02-16 16:33:47.061 3025-3025/com.xyd.activitylaunchmodedemo D/LogUtils➄: ╚══════════════════════════════════════════════════════════════

從日誌文件可以看出:在切換時,先調用onSaveInstanceState()方法,保存數據,然後切換之後調用onCreate和onRestoreInstanceState方法,獲取保存的數據。

2. 資源內存不足導致優先級低的activity被殺死

首先先分清activity的優先級,如下三種:

  1. 前臺activity —正在和用戶交互,優先級最高
  2. 可見但非前臺activity— 比如activity中彈出了一個dialog對話框,導致activity可見但是位於後臺,無法和用戶交互。
  3. 後臺activity — 已經被暫停的activity,比如A啓動B之後,A的優先級低,B的優先級最高

當系統內存不足時,系統會按照上邊的優先級,有低到高的優先級殺死目標activity所在的進程,並在後續通過onSaveInstanceState和onRestoreInstanceState 方法來存儲和恢復數據。如果一個進程中沒有四大組件在執行,那麼這個進程很快就會被系統殺死。

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