作者:路遥TM
Lifecycle(生命周期) 在任何 GUI 编程中都是基石般的存在,Android 也不例外。
作为用户,在页面跳转,旋转屏幕,查看通知,切换应用等日常操作中,都期望获得流畅连贯的使用体验。在这背后,就需要我们开发者在生命周期组件的不同阶段中进行相应的逻辑处理。这里的生命周期组件,可能是整个应用,也可能是单个页面。对应到 Android 中,Activity、Fragment,甚至 Service 都可以成为生命周期组件。
现在假设这样一个需求,你需要封装一个播放器的基础组件,供各个部门调用。最基本的流程就是打开 Activity,初始化资源并播放,退出 Activity,停止播放。
不假思索直接下笔,就很容易诞生下面这样的 “屎山代码” 。
class ShitAVPlayer {
fun init() {}
fun start() {}
fun stop() {}
}
调用方需要在 Activity/Fragment 等生命周期组件的不同生命周期回调中,调用相应的方法。
class VideoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
shitAVPlayer.init()
shitAVPlayer.start()
}
override fun onStop() {
super.onStop()
shitAVPlayer.stop()
}
}
功能实现上没有太大问题,但下面几个场景难免会给别人一种在屎山翻屎的感觉。
- 你的 ShitAVPlayer 作为基础组件提供给其他部门使用,当量级达到一定程度时,你没有办法保证每一个调用方都能合理且正确的处理生命周期,满地跑的内存泄漏一定少不了你的锅。
— 什么?你自己没调用,还赖我?
— 鬼知道我一个生命周期回调中要处理多少逻辑?你的 ShitAVPlayer 人如其名!
- 如果你的 ShitAVPlayer 需要在
onCreate()
中进行初始化,并提供了一个异步回调告知初始化状态,以判断是否可以开启。那么你可能无法保证执行回调时,生命周期组件是否已经onStop()
,这又得依靠调用方自行处理。这就可能造成不符合预期的生命周期情况。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
shitAVPlayer.init { success ->
// 是否还有必要开启
if (success) shitAVPlayer.start()
}
}
-
如果产品给你加了这么一个需求,播放时按 Home 键回到桌面要暂停播放,返回时再恢复播放。你三下五除二给
ShitAVPlayer
加了onResume()
和onPause()
方法,然后花费大量时间和各个调用方同步。— 老哥,有空在你的 Activity 的 onResume 和 onPause 回调加个方法呗,