使用FLAG_ACTIVITY_CLEAR_TASK与NEW_TASK启动Activity时生命周期顺序异常
通过AlarmReceiver启动一个Activity时,使用了Intent标记FLAG_ACTIVITY_CLEAR_TASK和FLAG_ACTIVITY_NEW_TASK。当目标Activity已处于运行且可见状态时,预期应该清除任务并重启它,但实际目标Activity的生命周期方法调用顺序始终为:
onPause(); onCreate(); onStart(); onResume(); onStop(); onDestroy();
值得注意的是,onDestroy()在onResume()之后才被调用,但Activity仍处于运行状态。想知道该现象是否正常?忽略了什么?
这个现象是正常的,属于Android系统任务栈调度和生命周期管理的优化行为,你忽略的是这两个Flag组合的实际作用逻辑,以及系统为保证前台界面可用性的调度顺序:
Flag组合的实际行为
FLAG_ACTIVITY_NEW_TASK+FLAG_ACTIVITY_CLEAR_TASK的作用是:清除目标Activity所属任务栈中的所有现有实例,然后在清理后的任务栈中启动一个新的Activity实例。当目标Activity已经处于前台运行时,系统不会直接销毁当前实例再启动新的,而是先完成新实例的前台就绪,再处理旧实例的销毁。生命周期顺序的原因
系统为了避免界面出现空白、保证用户体验,会优先让新的Activity实例完成初始化并显示到前台(也就是走完onCreate()→onStart()→onResume()),之后才会把旧的Activity实例从任务栈中移除,依次调用它的onStop()→onDestroy()。此时前台运行的是新创建的Activity实例,旧实例只是延迟销毁,并不影响新实例的正常运行。如果想要直接重启当前实例而非创建新实例
如果你的需求是复用当前Activity实例并重启它,而不是创建新实例后销毁旧的,可以换一种实现方式:
- 启动前先判断目标Activity是否处于前台(可通过ActivityManager获取当前栈顶Activity信息)
- 若已在前台,通过Intent传递自定义标记(比如
EXTRA_RESTART_ACTIVITY),在目标Activity的onNewIntent()方法中处理重启逻辑(比如重新加载数据、重置状态) - 此时无需使用
FLAG_ACTIVITY_CLEAR_TASK和FLAG_ACTIVITY_NEW_TASK,改用FLAG_ACTIVITY_SINGLE_TOP保证复用实例
内容的提问来源于stack exchange,提问作者user8533943

