哪些 android 生命周期方法保证在调用 finish() 之后被调用?
Which android lifecycle methods are guaranteed to be called after a call to finish()?
我有一个 activity A,它有几个以调用 finish() 结束的执行分支。阅读文档,我的理解是这将导致 onDestroy() 在某个时间点被调用 activity A if 和 when finish() 被调用。稍后,activity A 可能会被 activity B 重新启动。
但是,我观察到情况并非总是如此。在极少数情况下,在 activity A 由 activity B 在 activity A 调用 finish() 之后重新启动之前,不会调用 onDestroy()。如果 activity B 在 activity A 调用 finish() 之后很快重新启动 activity A,则尤其如此。这种可能性与生命周期图相匹配(参见 here)。
我的问题如下。假设 Activity A 处于 运行 状态并调用 finish()。关于 activity A 在 activity B 重新启动 activity A 之前调用 onPause() 或 onStop() 是否可以做出任何保证(无论将来如何 soon/late 重新启动) ?而且,一旦ActivityA重启,能保证onCreate()、onStart()、onResume()一定会被调用吗?换句话说,我的问题是如果 activity 处于 运行 状态并且 finish() 被调用,那么 activity 可能采取的生命周期图到 [=36] 的可能路径是什么=] 到 运行 状态?
tldr;
调用 finish() 将保证调用 onDestroy() 以便您可以优雅地清理内存中的对象。这也意味着如果相同的 activity 再次被调用到前台,我们将始终期望生命周期从头开始。
如果 onRestart() 被调用,这意味着 activity 没有被销毁,因此也意味着 onDestroy() 也没有被调用。 finish() 用于销毁 activity,这意味着 finish() 也从未被调用过。
如果调用 finish(),唯一确定的是 onDestroy() 将被调用。我相信可以调用其他生命周期方法,但取决于何时调用(activity 的当前状态)finish()。
如果调用 onDestroy(),将创建 activity 的新实例,这意味着它将从 onCreate() 开始。
您可以为每个生命周期方法添加日志输出并尝试从每个方法调用 finish() 并查看发生了什么。如果行为是一致的,如果您 want/need 将响应式代码添加到生命周期事件,您可以尝试确保您的逻辑在某个生命周期事件中被触发。
注意:当我们明确想要从内存中销毁 activity 时,我们调用 finish()。
更新:
"If finish() is called, the only certainty is that onDestroy() will be
called"
是 android 文档中定义的行为,这是我们应该期望的。如果并且当您观察到与预期不同的行为时,则这是代码可能无法正常运行的潜在迹象。在您的问题范围内,问题要么源自 android 环境,要么源自您的代码(更具体地说,您如何管理项目中的 Activity 导航)。
我会先与 official android issues tracker 确认一下,看看是否有与您所经历的类似的现有报告。然后我建议您查看您的应用如何处理活动之间的导航。
据我所知,finish()
的目的是让我们能够摧毁一个 activity at-will(而且它的摧毁应该是瞬间发生的)。所以如果你以某种方式退出 Activity A 进入 Activity B,然后退出 Activity B 到 re-enter Activity A,这个流程一定发生得相当快.不确定我们在这里谈论的速度有多快,但假设这就是您的应用程序的行为方式,那么您可能不需要调用 finish()
,因为您需要保留 activity 在 backstack 中。如果这不是您的应用程序应有的行为方式,那么您要么在创建一些奇怪的竞争条件,要么该应用程序实际上正在创建相同 Activity 的另一个实例 - 查看后台堆栈上的 link 解释关于 Activity 个任务。
提醒一下,这些只是建议,因为我不知道您的应用应该如何工作、它有什么作用以及代码是如何实现的。
Activity一个onPause()
,当你调用finish()
时,保证调用onStop()
。但是 onDestroy()
不保证在 activity A 重启 activity B 时被调用。当 activity A 在重启 onCreate()
、onStart()
和 onResume()
会分别被调用。
但是当你使用 activity Lifecycle
观察 activity.
的 Lifecycle.Event
时,保证会调用所有生命周期事件
您可以像下面这样测试自己看看:
class ActivityB : AppCompatActivity() {
override fun onResume() {
super.onResume()
startActivity(Intent(this, ActivityA::class.java))
}
}
class ActivityA : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("tag","onCreate")
lifecycle.addObserver(object:LifecycleEventObserver{
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
Log.d("lifecycleEvent","$event")
}
})
}
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")
}
}
finish() 会发生什么?
调用finish()
的方法将运行完成。在您 return 控制 Android 之前,finish()
行动甚至不会开始。因此,Activity 的每个生命周期事件,如 onCreate
、onResume
、onPause
、onDestroy
总是在单个线程上调用 - The Main thread
.
简而言之,此线程由队列支持,所有 activity 事件都发布到该队列中。这个线程可以按照插入的顺序执行所有这些事件。
如果您在 onCreate()
等生命周期回调之一中调用 finish()
,finish
消息将被添加到此队列中,但线程无法自由选择和执行finish
操作直到当前执行方法 returns 即线程从当前任务中释放。
ondestroy()
是您在 activity 被销毁之前收到的最后一个电话。这可能是因为 activity 正在完成(有人在其上调用 finish()
,或者因为系统正在临时销毁 activity 的这个实例以保存 space。你可以用isFinishing()
方法区分这两种情况。
如果有两个活动A
和B
。你的流程是从 A -> B
和 B=A
调用 finish()
,然后,你从中调用 finish()
的方法将按照 Mark 提到的那样执行。回调的流程如下-
onPause() of activity A
onRestart() > onStart() > onResume() of Activity B
然后,真正的区别来了。如果您没有从 activity A
调用 finish()
;这里只会调用 ctivity A
中的 onStop()
。而在这种情况下,我们从 Activity A
调用了 finish()
;所以 onStop()
和 onDestroy()
都会被调用 activity A
.
我有一个 activity A,它有几个以调用 finish() 结束的执行分支。阅读文档,我的理解是这将导致 onDestroy() 在某个时间点被调用 activity A if 和 when finish() 被调用。稍后,activity A 可能会被 activity B 重新启动。
但是,我观察到情况并非总是如此。在极少数情况下,在 activity A 由 activity B 在 activity A 调用 finish() 之后重新启动之前,不会调用 onDestroy()。如果 activity B 在 activity A 调用 finish() 之后很快重新启动 activity A,则尤其如此。这种可能性与生命周期图相匹配(参见 here)。
我的问题如下。假设 Activity A 处于 运行 状态并调用 finish()。关于 activity A 在 activity B 重新启动 activity A 之前调用 onPause() 或 onStop() 是否可以做出任何保证(无论将来如何 soon/late 重新启动) ?而且,一旦ActivityA重启,能保证onCreate()、onStart()、onResume()一定会被调用吗?换句话说,我的问题是如果 activity 处于 运行 状态并且 finish() 被调用,那么 activity 可能采取的生命周期图到 [=36] 的可能路径是什么=] 到 运行 状态?
tldr; 调用 finish() 将保证调用 onDestroy() 以便您可以优雅地清理内存中的对象。这也意味着如果相同的 activity 再次被调用到前台,我们将始终期望生命周期从头开始。
如果 onRestart() 被调用,这意味着 activity 没有被销毁,因此也意味着 onDestroy() 也没有被调用。 finish() 用于销毁 activity,这意味着 finish() 也从未被调用过。
如果调用 finish(),唯一确定的是 onDestroy() 将被调用。我相信可以调用其他生命周期方法,但取决于何时调用(activity 的当前状态)finish()。
如果调用 onDestroy(),将创建 activity 的新实例,这意味着它将从 onCreate() 开始。
您可以为每个生命周期方法添加日志输出并尝试从每个方法调用 finish() 并查看发生了什么。如果行为是一致的,如果您 want/need 将响应式代码添加到生命周期事件,您可以尝试确保您的逻辑在某个生命周期事件中被触发。
注意:当我们明确想要从内存中销毁 activity 时,我们调用 finish()。
更新:
"If finish() is called, the only certainty is that onDestroy() will be called"
是 android 文档中定义的行为,这是我们应该期望的。如果并且当您观察到与预期不同的行为时,则这是代码可能无法正常运行的潜在迹象。在您的问题范围内,问题要么源自 android 环境,要么源自您的代码(更具体地说,您如何管理项目中的 Activity 导航)。
我会先与 official android issues tracker 确认一下,看看是否有与您所经历的类似的现有报告。然后我建议您查看您的应用如何处理活动之间的导航。
据我所知,finish()
的目的是让我们能够摧毁一个 activity at-will(而且它的摧毁应该是瞬间发生的)。所以如果你以某种方式退出 Activity A 进入 Activity B,然后退出 Activity B 到 re-enter Activity A,这个流程一定发生得相当快.不确定我们在这里谈论的速度有多快,但假设这就是您的应用程序的行为方式,那么您可能不需要调用 finish()
,因为您需要保留 activity 在 backstack 中。如果这不是您的应用程序应有的行为方式,那么您要么在创建一些奇怪的竞争条件,要么该应用程序实际上正在创建相同 Activity 的另一个实例 - 查看后台堆栈上的 link 解释关于 Activity 个任务。
提醒一下,这些只是建议,因为我不知道您的应用应该如何工作、它有什么作用以及代码是如何实现的。
Activity一个onPause()
,当你调用finish()
时,保证调用onStop()
。但是 onDestroy()
不保证在 activity A 重启 activity B 时被调用。当 activity A 在重启 onCreate()
、onStart()
和 onResume()
会分别被调用。
但是当你使用 activity Lifecycle
观察 activity.
Lifecycle.Event
时,保证会调用所有生命周期事件
您可以像下面这样测试自己看看:
class ActivityB : AppCompatActivity() {
override fun onResume() {
super.onResume()
startActivity(Intent(this, ActivityA::class.java))
}
}
class ActivityA : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("tag","onCreate")
lifecycle.addObserver(object:LifecycleEventObserver{
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
Log.d("lifecycleEvent","$event")
}
})
}
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")
}
}
finish() 会发生什么?
调用finish()
的方法将运行完成。在您 return 控制 Android 之前,finish()
行动甚至不会开始。因此,Activity 的每个生命周期事件,如 onCreate
、onResume
、onPause
、onDestroy
总是在单个线程上调用 - The Main thread
.
简而言之,此线程由队列支持,所有 activity 事件都发布到该队列中。这个线程可以按照插入的顺序执行所有这些事件。
如果您在 onCreate()
等生命周期回调之一中调用 finish()
,finish
消息将被添加到此队列中,但线程无法自由选择和执行finish
操作直到当前执行方法 returns 即线程从当前任务中释放。
ondestroy()
是您在 activity 被销毁之前收到的最后一个电话。这可能是因为 activity 正在完成(有人在其上调用 finish()
,或者因为系统正在临时销毁 activity 的这个实例以保存 space。你可以用isFinishing()
方法区分这两种情况。
如果有两个活动A
和B
。你的流程是从 A -> B
和 B=A
调用 finish()
,然后,你从中调用 finish()
的方法将按照 Mark 提到的那样执行。回调的流程如下-
onPause() of activity A
onRestart() > onStart() > onResume() of Activity B
然后,真正的区别来了。如果您没有从 activity A
调用 finish()
;这里只会调用 ctivity A
中的 onStop()
。而在这种情况下,我们从 Activity A
调用了 finish()
;所以 onStop()
和 onDestroy()
都会被调用 activity A
.