5月28日 01:52

Android Activity生命周期有哪些回调方法?各自什么时机触发?

7个核心回调方法

Activity生命周期是Android面试的高频考点,理解每个回调的触发时机和正确用法,是写出稳定应用的基础。

onCreate()

Activity首次创建时调用。这是生命周期的入口,执行一次性的初始化工作:加载布局(setContentView)、初始化变量、恢复保存的状态。

kotlin
override 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定位、注册传感器监听——都在这里启动。

kotlin
override 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。如果在这里执行耗时操作(网络请求、数据库写入),会直接卡住界面切换。

kotlin
override fun onPause() { super.onPause() // 停止相机预览,释放独占资源 camera?.stopPreview() sensorManager.unregisterListener(this) }

onStop()

Activity完全不可见时调用。与onPause()的区别:onPause()时Activity可能还部分可见,onStop()时已完全被遮挡。适合释放不再需要的资源:注销广播、停止动画、持久化数据。

如果系统内存紧张,onStop()之后Activity可能被直接回收,不会再走到onDestroy()。因此关键数据的持久化不要拖到onDestroy()。

onDestroy()

Activity被销毁前的最后回调。执行最终的资源清理:关闭数据库连接、释放文件句柄、取消网络请求。

可以通过isFinishing()判断是正常结束(用户按返回键)还是系统配置变更导致的重建:

kotlin
override 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仍有焦点)
弹出全屏DialogonPause →(关闭后)→ 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时才会触发,正常创建不会调用。

kotlin
override 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——前者能保留任意大小的对象,后者只能存少量可序列化数据。

标签:Android