Android销毁活动,终止进程

128

嗨,我想知道Android是如何管理内存的,但我找不到确切的答案。假设我有一个应用程序,在当前活动堆栈中有5个活动(4个已停止,1个正在运行),没有连接任何服务。我按Home键,使所有活动停止。我启动一些占用内存的应用程序,设备总内存开始变低。问题是:

...我的应用程序会发生什么?

  1. 系统是否只会销毁其中一个或一些活动以回收内存?
  2. 系统是否会杀死整个应用程序进程?所有活动是否都将被完全销毁?
  3. 当我回到我的应用程序时,如果它被完全杀死,会发生什么?它会从头开始(像第一次启动)还是会尝试恢复先前的状态/如果是-只有在堆栈顶部的那一个还是全部?

更新:

在提出这个问题之前,我多次看过Activity生命周期,但它没有解答我的问题。我进行了一些测试,有了一些答案。 DDMS中的“停止进程”是测试的线索。

我没有测试问题1的答案,但随着指南的说法:

  

如果活动暂停或停止,则系统可以通过要求它完成或简单地终止其进程来从内存中删除该活动。

似乎可以温柔地销毁一个或多个活动(使用onDestroy方法),而不会杀死进程。当再次返回到它们时,您将只会得到(onCreate + bundle)。

问题2的答案:

是的。通常,系统会杀死整个进程,这意味着所有数据,包括活动和静态字段,都将被销毁。这不是很好-您不会收到任何已暂停/停止活动的onDestroy或finialize()信息。这就是为什么saveInstanceState()在onPause方法之前调用的原因。onPause基本上是您应该保存某些内容的最后一种方法,因为在此方法之后,您可能永远无法看到onStop或onDestroy。系统可以只是杀死进程,破坏所有东西并清除所有正在进行的操作。

第三个问题的答案:

当重新进入一个已经被杀死的应用程序时会发生什么?

  • 在Android 2.2之前 - 应用程序将从头开始,回到启动器活动。
  • 从2.2开始 - 系统将恢复先前的应用程序状态。这是什么意思?这意味着最后可见的活动将被重建(onCreate + bundle)。活动栈会怎样呢?堆栈没有问题,但是其中所有的活动都已死亡。当您按下返回按钮重新回到它时,每个活动都将被重建(onCreate + bundle)。 关于这件事还有一件事情:

通常,在用户从主屏幕重新选择该任务时,系统会在某些情况下清除任务(从根活动以上的堆栈中删除所有活动)。如果用户在一定时间内(如30分钟)没有访问该任务,则通常会执行此操作。

结论?

  1. 不要认为可以通过android:configChanges="orientation"来解决处理活动旋转问题。这样做会引发您甚至没有意识到的许多其他问题。
  2. 使用DDMS测试您的应用程序 - 停止进程按钮。 请参考此链接
  3. 使用静态变量时要小心。不要认为在活动1中初始化它们后,您将在活动2中初始化它们。初始化全局静态变量的唯一安全位置是应用程序类。
  4. 记住您可能永远看不到onStop或onDestroy。在onPause中关闭文件/数据库,停止下载器。当您想要应用程序在BG中执行某些操作时 - 使用前台服务。

就这样了...希望我的论文能对您有所帮助 :)


1
我有一个应用程序,当前活动堆栈上有5个活动。当然,它们都来自于我的同一个进程应用程序。 - Mark
4
谢谢,这正是我也想问的问题……你的问题和回答对我很有帮助。 - craigrs84
请参见:https://dev59.com/r2gu5IYBdhLWcg3wYWFX,https://dev59.com/yW035IYBdhLWcg3wbPfc - Pang
@Mark:这个问题现在解决了吗?如果解决了怎么样? - Ameer Moaaviah
这不是一个问题,而是一个疑问。答案已经在我的更新中提供了。它基于我的测试和深入调查 :) - Mark
显示剩余7条评论
2个回答

33

首先请看这个:

img1

onPause() 当系统即将开始恢复先前的活动时调用。这通常用于提交未保存的更改到持久数据、停止动画和其他可能正在消耗 CPU 的东西等。此方法的实现必须非常快,因为下一个活动直到此方法返回才会被恢复。紧随其后的是 onResume()(如果活动返回前台)或 onStop()(如果活动对用户不可见)。

onStop() 当活动不再对用户可见时调用,因为另一个活动已经恢复并覆盖了此活动。这可能是因为正在启动新活动、将现有活动带到此活动的前面或销毁此活动。紧随其后的是 onRestart()(如果此活动回来与用户交互)或 onDestroy()(如果此活动即将离开)。

因此,当您在设备上按“HOME”按钮时,当前的前台活动被放置在 onPause() 然后是 onStop(),其余 4 个应保持 onStop()

根据 Google 的文档:

如果一个活动在屏幕前台(堆栈顶部),它是活动的或正在运行的。 如果一个活动失去焦点但仍可见(也就是说,一个新的非全尺寸或透明活动已经在您的活动之上获得了焦点),它将被暂停。暂停的活动完全存活(它维护所有状态和成员信息并保持与窗口管理器的连接),但可以在极低内存情况下被系统杀死。 如果一个活动被完全遮挡,它将被停止。它仍然保留所有状态和成员信息,但不再对用户可见,所以它的窗口被隐藏,并且在需要其他地方的内存时通常会被系统杀死。 如果一个活动被暂停或停止,系统可以通过要求其完成或简单地终止其进程来将该活动从内存中删除。当它再次显示给用户时,它必须完全重新启动并恢复到先前的状态。
对于进程生命周期: 进程生命周期 3. 后台活动(即不可见且已暂停的活动)不再关键,因此系统可以安全地杀死其进程以回收内存供其他前台或可见进程使用。如果需要杀死其进程,当用户返回该活动(使其在屏幕上再次可见)时,其onCreate(Bundle)方法将被调用,并使用先前在onSaveInstanceState(Bundle)中提供的savedInstanceState来重新启动自己,以便将其状态恢复为用户上次离开的状态。
以上所有引用均来自: Android Developers Reference: Activity 确认系统可以在启动一些消耗内存的应用程序时销毁非活动状态的活动并回收内存。您可以在活动中实现isFinishing(),然后使用DDMS中的“kill”按钮检测哪些活动正在被系统删除。但我猜系统会首先销毁最旧的活动。但是,当“启动活动”被回收时,保留其他活动是没有意义的。 更新

这里有一些我从这里找到的观点:

停止状态

当一个活动不可见但仍在内存中时,我们称其为处于停止状态。停止的活动可以被重新唤醒并变成运行状态,或者可以被销毁并从内存中移除。

系统将活动保持在停止状态是因为用户很可能会想要很快返回到那些活动,并且重新启动一个已停止的活动比从头开始启动一个活动要便宜得多。这是因为我们已经将所有对象加载到内存中,只需将其全部带到前台即可。

停止的活动可以随时从内存中删除。


4
这个问题的文档说明相当混乱。但是只能杀掉整个进程,而不能杀掉单个组件(如活动、服务等)。请参见:https://dev59.com/z2sz5IYBdhLWcg3w9s2r#7576275 - greg7gkb
这个问题应该更新一下,包括@greg7gkb评论中链接里的信息,否则会误导人。 - Luke De Feo

1
系统能只销毁一个或几个我的活动来恢复内存吗? 是的。当需要内存时,Android会杀死在后台运行的活动。杀死一个或全部可能取决于某些条件。例如,暂停或停止可以使Android杀死一个活动或进程本身。在此处Activity 生命周期,您可以获得以下要点。我建议您完全阅读该页面。这肯定会解决您的疑虑。
如果一个活动失去了焦点但仍然可见(也就是说,一个新的非全屏或透明的活动在你的活动上方拥有焦点),它会被暂停。暂停的活动完全存活着(它保持所有状态和成员信息,并保持连接到窗口管理器),但在极端低内存情况下,系统可以将其杀死。
如果一个活动被完全遮挡,它就会停止。它仍然保留所有状态和成员信息,但对用户不再可见,因此它的窗口被隐藏,并且当需要在其他地方使用内存时,它经常会被系统杀死。
如果一个活动被暂停或停止,系统可以通过要求其完成或简单地终止其进程来从内存中删除该活动。当它再次显示给用户时,它必须完全重新启动并恢复到先前的状态。
系统会终止我的整个应用程序吗?所有的活动都会被完全销毁吗?
活动是指个体,而进程是指一组活动。再看一下上面的第三点,它会像所述的那样终止进程。
当我的应用程序被完全杀死后,返回应用程序会发生什么?
类似于重新启动。再次阅读第三点将为您提供一些答案,例如“当它再次显示给用户时,必须完全重新启动并恢复到先前的状态”。获取有关内存相关信息的更多信息here
编辑:
应用程序中的所有活动都在一个进程中运行。因此,当进程被杀死时,无论是5个还是10个活动都将被杀死,即重新启动。重新启动将导致您的应用程序从开头开始,没有保存的状态。

2
我至少看了5遍Activity生命周期,但它并没有回答我的问题。根据你所说的,当我的应用程序进程被终止时,当我返回应用程序时,它将恢复到先前的状态。因此,当我有5个停止的活动时......在进程被杀死时它们全部都会结束(onDestroy被调用)吗?当我回到我的应用程序时,所有活动是否都会恢复(onCreate + bundle),或者只有位于堆栈顶部的一个活动(对用户可见)? - Mark
1
应用程序中的所有活动都在一个进程中运行。因此,当进程被终止时,无论有5个还是10个活动,它们都将被终止,即重新启动。重新启动将导致您的应用程序从头开始,没有保存的状态。 - Vinay
1
几乎正确,但对于2.2及以上版本不适用。请查看我在页面顶部的更新。 - Mark
1
不,这是不正确的,也从未正确过。根据文档很容易让人感到困惑,但请参考:https://dev59.com/z2sz5IYBdhLWcg3w9s2r#7576275 - greg7gkb
2
@JJPA Android 无法销毁单个 Activity 以回收内存,它只能销毁进程。请参考 Dianne Hackbor 的答案,她是 Android 核心团队成员之一,参与了“内存杀手”的实现:https://dev59.com/z2sz5IYBdhLWcg3w9s2r#7576275。 - bcorso
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接