1. AMS与Activity生命周期概述
Android系统中的Activity Manager Service(AMS)是整个框架的核心组件之一,负责管理应用进程和Activity的生命周期。理解AMS如何协调Activity状态转换,对于开发稳定高效的Android应用至关重要。
每个Activity实例在其生命周期中会经历多种状态变化,从创建到销毁的完整过程涉及六个核心回调方法:
- onCreate()
- onStart()
- onResume()
- onPause()
- onStop()
- onDestroy()
这些回调方法构成了Activity生命周期的基本框架,AMS通过精确控制这些回调的触发时机,确保应用资源得到合理分配,同时提供流畅的用户体验。
2. Activity生命周期状态详解
2.1 创建阶段:onCreate()
当系统首次创建Activity时触发onCreate()回调。这是生命周期中第一个且必须实现的方法,主要执行一次性初始化操作:
kotlin复制override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
// 初始化UI组件
recyclerView = findViewById(R.id.recycler_view)
adapter = MyAdapter()
recyclerView.adapter = adapter
// 恢复保存的状态
if (savedInstanceState != null) {
currentPosition = savedInstanceState.getInt("position")
}
}
关键注意事项:
- 必须调用super.onCreate()
- 在此设置内容视图(setContentView)
- 检查savedInstanceState是否为空以恢复状态
- 避免在此执行耗时操作,会影响启动速度
2.2 可见阶段:onStart()与onStop()
onStart()在Activity变为可见时调用,此时Activity已准备好进入前台:
kotlin复制override fun onStart() {
super.onStart()
// 注册广播接收器
registerReceiver(networkReceiver, IntentFilter(CONNECTIVITY_ACTION))
// 恢复动画或视频播放
videoView.start()
}
onStop()在Activity完全不可见时调用,应释放不需要的资源:
kotlin复制override fun onStop() {
super.onStop()
// 取消广播注册
unregisterReceiver(networkReceiver)
// 暂停后台任务
dataLoader.cancel()
}
2.3 前台交互阶段:onResume()与onPause()
onResume()在Activity进入前台并可与用户交互时调用:
kotlin复制override fun onResume() {
super.onResume()
// 恢复传感器监听
sensorManager.registerListener(this, accelerometer, SENSOR_DELAY_NORMAL)
// 更新UI数据
updateDashboard()
}
onPause()在Activity失去焦点但仍部分可见时调用:
kotlin复制override fun onPause() {
super.onPause()
// 释放传感器资源
sensorManager.unregisterListener(this)
// 保存临时数据
preferences.edit().putInt("lastPosition", currentPosition).apply()
}
重要提示:onPause()执行时间应尽可能短,否则会影响下一个Activity的启动速度
3. AMS的进程管理机制
3.1 进程优先级划分
AMS根据Activity状态将进程分为五个优先级:
| 优先级 | 进程状态 | 描述 | 回收可能性 |
|---|---|---|---|
| 1 | 前台进程 | 正在与用户交互的Activity所在进程 | 最低 |
| 2 | 可见进程 | 包含可见但非前台的Activity | 低 |
| 3 | 服务进程 | 运行着已启动服务的进程 | 中等 |
| 4 | 后台进程 | 包含不可见Activity的进程 | 高 |
| 5 | 空进程 | 不包含任何活动组件的进程 | 最高 |
3.2 进程回收策略
当系统内存不足时,AMS会按照以下顺序回收进程:
- 首先回收空进程
- 然后回收后台进程
- 接着回收服务进程
- 最后才会考虑回收可见进程和前台进程
这种策略确保了用户正在交互的应用能获得最佳体验。
4. 生命周期与状态保存实战
4.1 处理配置变更
设备配置变更(如旋转屏幕)会导致Activity重建,正确处理状态保存至关重要:
kotlin复制override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("scrollPosition", recyclerView.computeVerticalScrollOffset())
outState.putString("editTextContent", editText.text.toString())
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
val position = savedInstanceState.getInt("scrollPosition")
recyclerView.scrollTo(0, position)
editText.setText(savedInstanceState.getString("editTextContent"))
}
4.2 ViewModel的最佳实践
ViewModel可以在配置变更时保留数据:
kotlin复制class UserViewModel : ViewModel() {
private val _userData = MutableLiveData<User>()
val userData: LiveData<User> = _userData
fun loadUser(userId: String) {
viewModelScope.launch {
_userData.value = repository.getUser(userId)
}
}
}
// 在Activity中使用
private lateinit var viewModel: UserViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
viewModel.userData.observe(this, { user ->
updateUI(user)
})
}
5. 常见问题与优化建议
5.1 内存泄漏预防
常见内存泄漏场景及解决方案:
-
静态引用Activity:
kotlin复制// 错误示例 companion object { var leakedActivity: Activity? = null } // 正确做法:避免静态引用或使用WeakReference companion object { private var weakActivity: WeakReference<Activity>? = null } -
未取消的Handler/Runnable:
kotlin复制private val handler = Handler(Looper.getMainLooper()) override fun onDestroy() { super.onDestroy() handler.removeCallbacksAndMessages(null) // 必须清理 } -
未关闭的Cursor/Stream:
kotlin复制override fun onStop() { super.onStop() cursor?.close() // 及时关闭数据库游标 inputStream?.close() }
5.2 性能优化技巧
-
延迟加载:
kotlin复制private val heavyView by lazy { findViewById<View>(R.id.complex_view) } override fun onStart() { super.onStart() if (shouldLoadHeavyView) { heavyView.visibility = View.VISIBLE } } -
分阶段初始化:
kotlin复制override fun onCreate() { super.onCreate() initEssentialComponents() // 必须的初始化 // 非关键初始化推迟到onStart handler.postDelayed({ initNonCriticalComponents() }, 300) } -
使用StrictMode检测问题:
kotlin复制if (BuildConfig.DEBUG) { StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .penaltyLog() .build()) }
6. 高级主题:多窗口模式处理
6.1 生命周期变化
在多窗口模式下,Activity的生命周期行为有所不同:
- 进入分屏:onPause()但不一定onStop()
- 调整大小:可能触发onConfigurationChanged()
- 获得焦点:onResume()
- 失去焦点:onPause()
6.2 适配建议
kotlin复制override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean) {
super.onMultiWindowModeChanged(isInMultiWindowMode)
if (isInMultiWindowMode) {
// 简化UI,释放非必要资源
reduceMemoryUsage()
} else {
// 恢复完整功能
restoreFullFeatures()
}
}
override fun onPictureInPictureModeChanged(isInPipMode: Boolean) {
super.onPictureInPictureModeChanged(isInPipMode)
if (isInPipMode) {
// 只保留视频播放器
keepOnlyVideoPlayer()
}
}
7. 测试与调试技巧
7.1 生命周期测试方法
使用AndroidX Test模拟生命周期变化:
kotlin复制@RunWith(AndroidJUnit4::class)
class LifecycleTest {
@get:Rule
val activityRule = ActivityScenarioRule(MainActivity::class.java)
@Test
fun testLifecycle() {
activityRule.scenario.moveToState(Lifecycle.State.CREATED)
activityRule.scenario.moveToState(Lifecycle.State.STARTED)
activityRule.scenario.moveToState(Lifecycle.State.RESUMED)
// 验证UI状态
onView(withId(R.id.text_view)).check(matches(isDisplayed()))
}
}
7.2 ADB调试命令
通过ADB命令强制触发生命周期变化:
bash复制# 启动Activity
adb shell am start -n com.example/.MainActivity
# 发送HOME键(触发onPause/onStop)
adb shell input keyevent KEYCODE_HOME
# 发送BACK键(可能触发onDestroy)
adb shell input keyevent KEYCODE_BACK
# 模拟内存压力
adb shell am send-trim-memory com.example RUNNING_LOW
理解AMS的核心机制和Activity生命周期对于开发高质量Android应用至关重要。通过合理利用生命周期回调,优化资源管理,并正确处理状态保存,可以显著提升应用性能和用户体验。在实际开发中,建议结合ViewModel、LiveData等架构组件,构建更健壮的生命周期感知型应用。
