2. Activity 生命周期日志追踪与状态保存

Activity 生命周期日志追踪与状态保存 学习卡片

生命周期回调与日志观察点

Activity 从创建到销毁会依次经过 onCreate → onStart → onResume → onPause → onStop → onDestroy,旋转屏幕或切换后台时还会触发 onSaveInstanceState 与 onRestoreInstanceState。本案例在 MainActivity 中重写这些回调并打印带标记的日志,用计数器验证状态保存是否生效。

Activity 生命周期状态迁移与回调触发 Created Started Resumed Paused Stopped Destroyed onStart onResume onPause onStop onDestroy 旋转屏幕 / 切换后台时的状态保存与恢复 onSaveInstanceState putInt("count", count) 系统重建 Activity onCreate(savedInstanceState) onRestoreInstanceState getInt("count") 恢复计数 关键:savedInstanceState 为 null 时表示首次创建,非 null 时表示重建恢复

在 MainActivity 中埋入日志与计数

下面代码在全部生命周期回调中调用 Log.d(TAG, ...),并用一个 count 变量配合按钮递增。旋转屏幕后若计数不归零,说明 onSaveInstanceState 与恢复逻辑生效。

class MainActivity : AppCompatActivity() {

    private val TAG = "LifeCycle"
    private var count = 0
    private lateinit var tvCount: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(TAG, "onCreate: savedInstanceState=${savedInstanceState != null}")

        tvCount = findViewById(R.id.tvCount)
        val btnAdd = findViewById<Button>(R.id.btnAdd)

        // 首次创建时 savedInstanceState 为 null;重建时从中恢复计数
        savedInstanceState?.let {
            count = it.getInt("count", 0)
            Log.d(TAG, "onCreate: 恢复 count=$count")
        }
        tvCount.text = "计数:$count"

        btnAdd.setOnClickListener {
            count++
            tvCount.text = "计数:$count"
            Log.d(TAG, "点击递增 count=$count")
        }
    }

    override fun onStart() { super.onStart(); Log.d(TAG, "onStart") }
    override fun onResume() { super.onResume(); Log.d(TAG, "onResume") }
    override fun onPause() { super.onPause(); Log.d(TAG, "onPause") }
    override fun onStop() { super.onStop(); Log.d(TAG, "onStop") }
    override fun onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy") }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putInt("count", count)
        Log.d(TAG, "onSaveInstanceState: 保存 count=$count")
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)
        count = savedInstanceState.getInt("count", 0)
        tvCount.text = "计数:$count"
        Log.d(TAG, "onRestoreInstanceState: 恢复 count=$count")
    }
}
布局文件只需一个 TextView(id 为 tvCount)和一个 Button(id 为 btnAdd)。在 Logcat 中过滤 LifeCycle 标签即可看到完整回调序列。

旋转屏幕与切换后台的日志判读

在模拟器中点击计数按钮若干次,然后旋转屏幕,观察 Logcat 输出。典型日志序列如下(示例,实际顺序以设备为准):

操作预期日志序列计数表现
首次启动onCreate → onStart → onResume0
点击递增 3 次点击递增 count=1/2/33
旋转屏幕onPause → onSaveInstanceState → onStop → onDestroy → onCreate → onStart → onRestoreInstanceState → onResume仍为 3
按 Home 键onPause → onSaveInstanceState → onStop保持
返回前台onRestart → onStart → onResume保持
按返回键退出onPause → onStop → onDestroy—
若旋转后计数归零,检查 onSaveInstanceState 是否调用了 super,以及 onCreate 中是否读取了 savedInstanceState。注意:onSaveInstanceState 在 Android 9(API 28)及以上会在 onStop 之后调用,但顺序不影响保存结果。

验证清单

  • Logcat 过滤 LifeCycle 能看到全部回调日志。
  • 旋转屏幕后计数不归零,且日志中出现 onSaveInstanceState 与 onRestoreInstanceState。
  • 按 Home 键再返回,计数保持,日志出现 onRestart。
  • 按返回键退出,日志出现 onDestroy,且不再有后续回调。