Android Activity生命周期有哪些回调方法?各自什么时机触发?
7个核心回调方法
Activity生命周期是Android面试的高频考点,理解每个回调的触发时机和正确用法,是写出稳定应用的基础。
onCreate()
Activity首次创建时调用。这是生命周期的入口,执行一次性的初始化工作:加载布局(setContentView)、初始化变量、恢复保存的状态。
kotlinoverride fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 恢复保存的状态 if (savedInstanceState != null) { val value = savedInstanceState.getString("key") } }
注意:此时Activity尚未可见,不要在这里启动动画或执行需要可见UI的操作。
onStart()
Activity即将变为可见时调用。此时Activity已经出现在屏幕上,但用户还无法与之交互。适合做轻量级的准备工作,比如注册广播接收器、初始化UI动画。
Activity从停止状态回到前台时也会经过此方法,因此onStart()中的逻辑每次可见都会执行,不要放只应执行一次的初始化代码。
onResume()
Activity获得焦点、可以与用户交互时调用。此时Activity位于前台,处于活跃状态。需要独占资源的操作——比如打开相机、开始GPS定位、注册传感器监听——都在这里启动。
kotlinoverride fun onResume() { super.onResume() cameraManager.openCamera(cameraId, stateCallback, backgroundHandler) sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) }
onPause()
Activity失去焦点时调用。此时Activity可能仍然部分可见(比如被透明或浮层Activity遮挡),但用户无法与之交互。这是保存未提交数据和释放非关键资源的安全位置。
关键约束:onPause()必须快速执行。系统在前一个Activity的onPause()返回之前,不会启动新的Activity。如果在这里执行耗时操作(网络请求、数据库写入),会直接卡住界面切换。
kotlinoverride fun onPause() { super.onPause() // 停止相机预览,释放独占资源 camera?.stopPreview() sensorManager.unregisterListener(this) }
onStop()
Activity完全不可见时调用。与onPause()的区别:onPause()时Activity可能还部分可见,onStop()时已完全被遮挡。适合释放不再需要的资源:注销广播、停止动画、持久化数据。
如果系统内存紧张,onStop()之后Activity可能被直接回收,不会再走到onDestroy()。因此关键数据的持久化不要拖到onDestroy()。
onDestroy()
Activity被销毁前的最后回调。执行最终的资源清理:关闭数据库连接、释放文件句柄、取消网络请求。
可以通过isFinishing()判断是正常结束(用户按返回键)还是系统配置变更导致的重建:
kotlinoverride fun onDestroy() { super.onDestroy() if (isFinishing) { // 用户主动退出,彻底清理 releaseAllResources() } // 配置变更导致的销毁,ViewModel中的数据不需要清理 }
onRestart()
Activity从停止状态重新启动时调用,之后会走onStart() → onResume()。这个回调使用频率不高,主要用于在Activity重新可见前做一些恢复工作,比如刷新可能过时的UI数据。
典型场景下的生命周期流程
| 场景 | 回调顺序 |
|---|---|
| 首次打开 | onCreate → onStart → onResume |
| 跳转到其他Activity | 当前Activity: onPause → onStop |
| 从其他Activity返回 | onRestart → onStart → onResume |
| 按Home键切到后台 | onPause → onStop |
| 从后台回到前台 | onRestart → onStart → onResume |
| 按返回键退出 | onPause → onStop → onDestroy |
| 弹出Dialog | 不触发生命周期回调(Activity仍有焦点) |
| 弹出全屏Dialog | onPause →(关闭后)→ onResume |
| 横竖屏切换(默认) | onPause → onStop → onDestroy → onCreate → onStart → onResume |
| 横竖屏切换(configChanges) | onConfigurationChanged,不重建 |
面试高频追问
两个Activity跳转时,生命周期回调的先后顺序是什么?
从Activity A跳转到Activity B,执行顺序是:
A.onPause → B.onCreate → B.onStart → B.onResume → A.onStop
注意:是A的onPause先执行完,B才开始创建。这再次说明onPause不能做耗时操作。
onSaveInstanceState和onRestoreInstanceState在什么时候调用?
onSaveInstanceState在Activity可能被系统回收之前调用,确保在onStop之前。典型场景:按Home键、切换到其他Activity、屏幕旋转。
onRestoreInstanceState在Activity被重建后、onStart之后调用。只有当系统确实回收并重建了Activity时才会触发,正常创建不会调用。
kotlinoverride fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString("edit_text_content", editText.text.toString()) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) val content = savedInstanceState.getString("edit_text_content") editText.setText(content) }
也可以在onCreate中通过判断savedInstanceState是否为null来恢复数据,但onRestoreInstanceState更安全——它保证了Bundle一定非空。
如何避免横竖屏切换时Activity重建?
在AndroidManifest中为Activity添加configChanges属性:
xml<activity android:name=".MainActivity" android:configChanges="orientation|screenSize|keyboardHidden" />
这样屏幕旋转时只回调onConfigurationChanged,不会走销毁重建流程。但更推荐的做法是配合ViewModel,让数据在配置变更时自动保留,而不是禁止重建。
ViewModel与生命周期的关系是什么?
ViewModel的生命周期独立于Activity的配置变更。当Activity因横竖屏切换而销毁重建时,ViewModel不会被清除,新创建的Activity实例会拿到同一个ViewModel对象。只有当Activity真正结束(isFinishing为true)时,ViewModel的onCleared()才会被调用。
这就是为什么推荐用ViewModel保存UI数据,而不是用onSaveInstanceState——前者能保留任意大小的对象,后者只能存少量可序列化数据。