Android 入门笔记(2)
一、Activity 是什么?
简单来说,一个 Activity 就是应用中的一个单一屏幕。它负责提供一个用户界面(UI),用户可以通过这个界面进行交互(比如点击、输入等)。
类比:可以把它想象成桌面应用程序中的一个窗口,或者浏览器中的一个标签页。
应用组成:一个应用通常由多个 Activity 组成。例如,一个电子邮件应用可能有一个 Activity 显示收件箱列表,另一个 Activity 用于编写邮件,还有一个 Activity 用于阅读邮件。
主导 Activity:任何时候,只有一个 Activity 处于前台并获得用户焦点。其他 Activity可能处于停止、暂停状态,或者在后台。
二、为什么需要生命周期?
Activity 的生命周期是由 Android 系统,而非应用本身直接管理的。系统会根据用户的操作、设备状态的变化(如来电、屏幕旋转、内存不足等)来启动、暂停、恢复或销毁 Activity。
为了提供一个流畅、稳定、可预测的用户体验,Activity 必须能够响应这些状态变化。例如:
当用户切换到另一个应用时,当前的 Activity 应该暂停并释放不必要的资源(如摄像头)。
当用户返回时,它应该恢复并重新获取资源。
当系统需要回收内存时,它会选择销毁不活跃的 Activity,但需要提供机制让 Activity保存其状态,以便之后能够还原。
生命周期回调方法(如 onCreate, onPause)就是系统提供给我们的挂钩(Hooks),让我们可以在 Activity 状态变化的恰当时机执行相应的代码。
三、生命周期状态与回调方法
Activity 的生命周期可以概括为三个核心状态和六个关键的回调方法。下图是其经典的生命周期流程图(即使无法显示,也请先记住这个结构,下文会详解):
核心状态:
Resumed(活动/运行):Activity 位于屏幕前台,用户可与它交互。
Paused(暂停):Activity 被部分遮挡(如出现一个透明或非全屏的对话框)。它仍然存活,但用户无法与之交互。在极低内存情况下可能被系统杀死。
Stopped(停止):Activity 被完全遮挡(用户跳转到了另一个全屏 Activity)。它仍在后台,但已不可见。系统需要内存时很可能会优先杀死它。
核心回调方法:
系统会在 Activity 状态变化时按顺序调用这些方法。你必须在 Activity 子类中重写这些方法,以执行适当的行为。
class MainActivity : AppCompatActivity() {// 1. 创建 Activity: MUST DO 的方法override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) // 必须首先调用父类方法setContentView(R.layout.activity_main) // 设置UI布局,充气视图// 初始化必备的组件:ViewModel、绑定视图、设置点击监听器、加载列表数据等。// 参数 `savedInstanceState` 包含之前被系统销毁后保存的数据(如旋转屏幕后),如果是全新启动则为null。Log.d("Lifecycle", "onCreate Called")}// 2. Activity 即将可见override fun onStart() {super.onStart()// 应用对用户即将可见。可以开始一些需要显示UI的操作(如动画),// 或者初始化在 onStop() 中释放的组件。Log.d("Lifecycle", "onStart Called")}// 3. Activity 开始交互override fun onResume() {super.onResume()// Activity 进入 Resumed 状态,来到前台。这是应用最活跃的状态。// 必须在这里启动或恢复最核心的功能:摄像头预览、播放音频、动画等。Log.d("Lifecycle", "onResume Called")}// 4. Activity 失去焦点(部分可见)override fun onPause() {super.onPause()// 系统正在准备将 Activity 置于后台或部分遮挡。// 应该在这里暂停或释放那些不需要在后台运行的功能:暂停动画、摄像头、GPS等。// 操作必须快速完成,否则会拖慢下一个Activity的启动。// 注意:不要做太繁重的工作,因为如果下一个Activity是透明的,此Activity可能仍部分可见。Log.d("Lifecycle", "onPause Called")}// 5. Activity 完全不可见override fun onStop() {super.onStop()// Activity 不再可见。可以释放几乎所有在 onStart/onResume 中申请的不再需要的资源。// 执行轻量级的保存操作(如将数据暂存到数据库),为可能发生的销毁做准备。// 如果系统此时需要内存,可能会在不调用 onDestroy() 的情况下直接终止进程。Log.d("Lifecycle", "onStop Called")}// 6. Activity 被销毁override fun onDestroy() {super.onDestroy()// Activity 被彻底销毁(用户按下返回键或主动调用了 finish())。// 这是最后的清理机会:终止网络请求、解除绑定服务、移除所有注册的监听器以防止内存泄漏。Log.d("Lifecycle", "onDestroy Called")}
}
四、两个特殊的回调:保存和恢复状态
除了上述核心方法,还有两个至关重要的方法用于处理配置变更(如屏幕旋转、语言切换) 导致的 Activity 销毁和重建。
onSaveInstanceState(outState: Bundle):
何时调用:当 Activity 可能被系统销毁时(如配置变更或内存回收),在 onStop() 之后被调用。注意:用户主动按返回键销毁时不会调用。
做什么:你需要将希望恢复的临时性 UI 数据(如输入框中的文本、列表滚动位置)存入 Bundle 对象。这个 Bundle 之后会传递给 onCreate() 和 onRestoreInstanceState()。
Kotlin 示例:
override fun onSaveInstanceState(outState: Bundle) {super.onSaveInstanceState(outState)// 保存当前输入框的文本outState.putString("EDITOR_TEXT", binding.editText.text.toString())
}
onRestoreInstanceState(savedInstanceState: Bundle):
何时调用:只有在确实有保存的状态需要恢复时,才会在 onStart() 之后被调用。
做什么:从 Bundle 中取出数据并恢复 UI 状态。通常在这里恢复比在 onCreate() 中更方便,因为此时视图层级已经构建完成。
Kotlin 示例:
override fun onRestoreInstanceState(savedInstanceState: Bundle) {super.onRestoreInstanceState(savedInstanceState)// 恢复输入框的文本val savedText = savedInstanceState.getString("EDITOR_TEXT", "")binding.editText.setText(savedText)
}
在 onCreate() 中恢复:
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// ...if (savedInstanceState != null) {val savedText = savedInstanceState.getString("EDITOR_TEXT", "")binding.editText.setText(savedText)}
}
重要提示:对于永久性数据(如用户个人资料),应使用数据库(Room) 或 ViewModel(它能在配置变更后存活)来保存,而不是依赖 onSaveInstanceState。
五、实际场景中的生命周期流转
启动一个 Activity:
onCreate() -> onStart() -> onResume()
用户按下“返回”键:
onPause() -> onStop() -> onDestroy()
(因为用户主动结束,此Activity实例将彻底消失)
用户按下“主页”键或接到来电:
onPause() -> onStop()
(Activity仍在后台,可能被杀死)
用户从最近任务列表切换回应用:
onRestart() -> onStart() -> onResume()
屏幕旋转(配置变更):
旧 Activity: onPause() -> onSaveInstanceState() -> onStop() -> onDestroy()
新 Activity: onCreate(savedInstanceState) -> onStart() -> onRestoreInstanceState() -> onResume()
(注意:旧Activity被销毁,但系统用Bundle保存并传递了它的状态给新Activity)
六、最佳实践与总结
初始化与释放对应:在 onCreate()/onResume() 中初始化的资源,应在 onDestroy()/onPause()/onStop() 中相应地释放,防止资源泄漏。
轻量化 onPause() 和 onStop():这些方法需要快速执行完毕,不要在其中进行繁重的操作。
使用 ViewModel:强烈推荐使用 ViewModel 来存储和管理界面相关的数据。ViewModel 的生命周期比 Activity 长(仅限于配置变更),可以优雅地解决屏幕旋转等场景下的数据丢失问题。
使用 onSaveInstanceState 保存轻量UI状态:用于恢复短暂的、与UI相关的状态(如文本、滚动位置),而不是复杂数据。