Android基础 - activity生命周期

Posted 我叫白小飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android基础 - activity生命周期相关的知识,希望对你有一定的参考价值。

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会被销毁,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= ActivityRecord76602aa 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 方法来存储和恢复数据。如果一个进程中没有四大组件在执行,那么这个进程很快就会被系统杀死。

以上是关于Android基础 - activity生命周期的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin基础从入门到进阶系列讲解(进阶篇)Android之Activity的生命周期

Android Studio基础-Activity生命周期与多个Activity跳转

Android Studio基础-Activity生命周期与多个Activity跳转

Android开发基础之Activity,图解Activity状态与生命周期

Android开发基础之Activity,图解Activity状态与生命周期

Android零基础入门第75节:Activity状态和生命周期方法