我有一个活动A,它有几个执行分支,以调用finish()结束。阅读文档后,我的理解是,如果调用finish(),则在活动A的某个时候调用onDestroy()。稍后,活动A可能由活动B重新启动。
然而,我注意到,这并不总是发生的事情。在少数情况下,在活动A调用finish()之后,活动B重新启动活动A之前不调用onDestroy()。如果活动B在活动A调用finish()之后不久就重新启动活动A,则尤其如此。这种可能性与生命周期图相匹配(请参阅这里)。
我的问题如下。假设活动A处于运行状态,并调用finish()。在活动B重新启动活动A之前,是否可以保证活动A调用onPause()或onStop() (不管重启发生的时间有多快/晚)?此外,一旦活动A重新启动,是否可以保证调用onCreate()、onStart()或onResume()?换句话说,我的问题是,如果一个活动处于运行状态,并且称为finish(),那么在活动返回到运行状态所需的生命周期图中,有哪些可能的路径?
发布于 2022-04-28 13:08:48
Activity onPause()
和onStop()
是在调用finish()
时被调用的保证。但是当活动A重新启动活动B时,不能保证调用onDestroy()
。当活动A重新启动时,onCreate()
、onStart()
和onResume()
将分别被调用。
但是,当您使用活动Lifecycle
来观察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")
}
}
发布于 2022-05-03 11:41:21
完成()发生了什么?
调用finish()
的方法将运行到完成。在您将控制权返回到Android之前,finish()
操作甚至不会开始。因此,活动的每个生命周期事件(如onCreate
、onResume
、onPause
、onDestroy
)总是在单个线程- The Main thread
上调用。
简而言之,这个线程是由一个队列支持的,所有的活动事件都会被发布到队列中。此线程可以按照插入顺序执行所有这些事件。
如果在生命周期回调(如finish()
)中调用finish
,则会向该队列中添加finish
消息,但在当前执行的方法返回之前,线程不能自由地选择和执行finish
操作,也就是说线程将从当前任务中解脱出来。
ondestroy()
是在您的活动被破坏之前收到的最后一个电话。这可能是因为活动正在结束(有人在其上称为finish()
),或者因为系统正在临时销毁该活动的这个实例以节省空间。您可以使用isFinishing()
方法区分这两种场景。
如果有两个活动,A
和B
。您的流程来自A -> B
,B=A
调用finish()
,然后,调用finish()
的方法将如Mark提到的那样执行。回调的流程如下-
onPause() of activity A
onRestart() > onStart() > onResume() of Activity B
然后,真正的区别来了。如果您没有从ActivityA
调用finish()
;这里将只调用onStop()
of ctivity A
。而在本例中,我们从Activity A
调用了Activity A
;因此onStop()
和onDestroy()
都将用于activity A
。
发布于 2022-04-27 06:04:33
调用finish()将确保调用onDestroy(),以便您能够优雅地清理内存中的对象。这也意味着,如果同一活动再次被调用到前台,我们将始终期望生命周期从一开始就开始。
如果调用了onRestart(),这意味着活动没有被销毁,因此也意味着onDestroy()也没有被调用。finish()用于销毁一个活动,这意味着finish()也从未被调用过。
如果调用finish(),唯一确定的是将调用onDestroy()。我相信可以调用其他生命周期方法,但取决于何时(活动的当前状态) finish()被调用。
如果调用onDestroy(),将创建该活动的新实例,这意味着它将从onCreate()开始。
您可以为每个生命周期方法添加日志输出,并尝试从每个方法调用finish(),看看会发生什么。如果行为是一致的,如果希望/需要向生命周期事件添加反应性代码,则可以尝试确保在特定生命周期事件中触发逻辑。
注意:当我们明确地希望从内存中销毁活动时,我们调用finish()。
更新:
“如果调用finish(),唯一确定的是onDestroy()将被调用”
是android文档中定义的行为,这是我们应该期待的。如果和当您观察的行为与预期不同,那么这是一个潜在的迹象,表明代码可能运行不当。在您的问题范围内,问题要么源于android环境,要么来自您的代码(更具体地说,您是如何管理项目中的活动导航的)。
我首先要检查一下官方android问题跟踪器,看看是否有任何与您所经历的类似的现有报告。然后,我建议您回顾一下您的应用程序如何处理活动之间的导航。
据我所知,finish()
的目的是让我们随心所欲地摧毁一项活动(而且它的破坏应该是即时的)。因此,如果你以某种方式退出活动A进入活动B,然后退出活动B以重新进入活动A,这种流动必须发生得相当快。不确定我们在这里讨论的速度有多快,但假设这是应用程序的行为方式,那么您可能不需要调用finish()
,因为您希望保留背叠中的活动。如果您的应用程序不是这样运行的,那么您要么正在创建一些奇怪的竞争条件,要么该应用程序实际上正在创建同一个活动的另一个实例--查看后台链接说明活动任务。
作为提醒,这些只是建议,因为我不知道你的应用程序应该如何工作,它做什么,以及代码是如何实现的。
https://stackoverflow.com/questions/71963255
复制相似问题