Android应用程序组件销毁和重建的详细信息。

20

请问是否有关于以下问题的具体、可信赖(最好简洁)的信息:

  1. 系统销毁组件的顺序和(如果适用)重新创建顺序 (Fragment、Activity、Activity 的线程/AsyncTasks/Timers、静态数据(类何时卸载?)、其他类中的线程/AsyncTasks/Timers、主机 TabActivity、ActivityGroup、绑定的本地服务、Application、进程) 无论应用程序处于后台还是前台。
    哪些状态可以遇到以停止销毁(例如在返回应用程序时可以遇到的状态,如“包括 Application 对象在内的所有内容都被销毁,但进程仍然存在”)?

  2. 是否可以在不修改 Android 的情况下以编程方式自行引起相同类型的销毁, 使其与系统所做的销毁不可区分,或者我们自己选择释放内存时需要单独的机制(由 onLowMemory 触发)?

  3. 1)所有场景的可靠复现步骤(junit.framework 是否可用?我还没有调查过)?

  4. 如果用户长时间离开任务,系统会清除该任务中除根活动外的所有活动。当用户再次返回任务时,只会还原根活动”:这是与进程/组件生命周期/销毁无关,还是与之相关?

我已经阅读了各种来源给出的信息碎片,通常不完整和误导,有时错误。
我承认,我略读了文档的某些部分,可能错过或误解了一些内容。

[编辑] 为避免误解:我所问的是 Android 销毁组件以释放内存,绕过 Activity.onDestroy。
当我将应用程序置于后台并稍后返回时,将发生以下序列之一:

  • onPause、onStop、onRestart、onStart、onResume
  • onPause、onStop、Application.onCreate、onCreate(非空)、onStart、onResume

[编辑2] 开启悬赏。需要关于 Activities、Fragments、Application、绑定的(潜在的远程)Services、进程的可靠信息。
部分/全部销毁场景。请参见第一个问题。


4
我所询问的是Android是否会销毁组件以释放内存-- Android不会销毁组件来释放内存。它会终止进程以释放内存。 - CommonsWare
@CommonsWare 这里的措辞:http://developer.android.com/training/basics/activity-lifecycle/stopping.html 和 http://developer.android.com/training/basics/activity-lifecycle/recreating.html,指的是“Activity”而不是“进程”。它甚至说:“一旦您的活动停止,如果需要恢复系统内存,系统可能会销毁实例。在极端情况下(...)杀死您的应用程序进程”,因此,除非这是极其误导性的文档,否则进程终止是“极端”的,单个活动也可以被销毁。 - kaay
此外,我记得当我返回一个应用程序并看到活动被重新创建时,进程仍然存在。如果进程被杀死,这种情况就不会再发生了。这导致我编写了我的第4点答案。 - kaay
1
文档有误。http://commonsware.com/blog/2011/10/03/activities-not-destroyed-to-free-heap-space.html - CommonsWare
@CommonsWare 终于有点实质性的东西了,非常感谢。现在如果这里有一个我可以授予赏金的答案就好了...最好也涉及到onStop和问题的第四点。 - kaay
6个回答

2
这要归功于hackbod写下了这篇文章(请阅读整个答案),以及CommonsWare在评论中提供了链接。

简而言之:所有文档都被反复修改,但它们仍然误导我们。它们并不是在误导我们,而是给我们提供了错误的信息。除非你正在使用Fragments(不知道support v4是否也算),否则Android通过杀死整个进程或什么也不做来释放内存。

当然,这并不能解决所有问题:
问题的第4点是什么?
为什么在处理所有配置更改的活动堆栈上按返回键时,我经常看到onCreate(notNull)?
这与广泛接受的信念有何关系,即onPause是您可以肯定得到的最后一个调用,而onStop可能永远不会被调用(那么应用程序如何进入后台以被杀死?)
我们正在取得一些进展。

更正:我们一无所获。上述问题仍未得到回答。 - kaay

2
这是我个人的经验,也是我询问过的开发人员的经验:
    • Fragment不会自动销毁。
    • 应用程序堆栈上的非可见Activity可以按任意顺序和数量自动销毁。
    • 销毁的Activity(或任何其他类的)线程和静态变量在Application被销毁之前都不会受到影响。
    • TimerTasks:未测试。
    • 绑定本地服务:在最后一个绑定的Activity和Application被销毁之间销毁。
    • Application是进程中最后一个销毁的东西,并且随着所有线程一起“消失”。
    • 除非您有自动任务杀手,否则进程可能在Application对象被销毁后长时间存在(20分钟以上)。
    • 在TabActivity下或ActivityGroups中的活动不会自动销毁,但如果容器被销毁,则全部消失。
      例如:在选项卡下具有选项卡下ActivityGroup的TabActivity。所有活动都存活。启动另一个全屏幕活动。现在,Android可以将包含所有内容的TabActivity一次性销毁或者完全不销毁。

  1. 如果手动销毁Activity,则它将经历整个生命周期,并且在再次启动时不会传递Bundle给onCreate。
    此外,onLowmemory不可靠-即使使用小的分配步骤,它可能在OutOfMemoryError被抛出之前永远不会被调用。

  2. 尽管自动销毁/恢复是Android中的一个重要功能,但没有任何方法可以测试这种情况。
  3. 这可能仅与进程是否仍然存在有关。如果存在,则Android将尝试恢复旧的活动。如果没有,则进行干净的重启。

以上内容包含一些假设。
我仍在等待某人确认并提供一些文档(不依赖于类的当前实现的保证)。
如果有任何错误,请务必纠正我。

编辑:上述信息可能已过时,它是在Android 2.1-2.3上测试的。


1

嗯,朋友,我猜你在研究中会遇到很多麻烦。基本上因为你在谈论两个黑盒子:Dalvik垃圾回收器和Android堆管理器。我会说你不能相信Android会按任何对象销毁的顺序来执行。但是,你可以相信这个生命周期会被遵循 [Programming Android, 2011]:

Activity生命周期:

onCreate() - Called after the instance of the activity has been created for the first  time
onRestart() - Called after an activity has been interrupted, just before the onStart();
onStart() - Called when the object activity and their visions become visible to the user;
onResume()-  Called when the object activity and their visions become interactive to the user;
onPause() - Called when a different instance of the activity is going to get visible and the present activity ceases to interact with the user
onStop() - Called when the activity is no longer visible or is not interacting
onDestroy() - Called when an activity instance must be destroyed and it's no longer needed. 

碎片有不同的生命周期,包括 onAttach、onCreateView 和 onActivityCreated 方法。 但是,你为什么要关心对象销毁的顺序?我看不出你需要监控这些事件的任何理由,但如果你确实需要,可以了解更多垃圾收集器的知识。

  1. 这只涵盖了Activity仅显示一次的情况。
  2. 我收到了构建具有类似IOS导航的应用程序的请求 - 带有自己的返回堆栈的嵌套选项卡。我没有设计它的机会。我需要处理onCreate(notNull)在从启动的视频播放器返回20分钟后导航回退堆栈,以及低内存问题。当我遇到大多数这些问题时,还没有Fragment,但这并不改变我可能再次遇到类似问题的事实,而且我的观察结果既不符合文档,也不符合hackbod的声明与前者相矛盾。
- kaay
此外,您似乎在暗示我阅读有关GC的内容将带领我找到一种监视重建顺序的方法。我不认为这是正确的。尽管如此,这将非常有用,因为它不仅会告诉我为什么会发生某些奇怪的情况,而且还会通过数周的测试(可悲地)显示要准备好哪些事情:在哪个时刻初始化连接,在哪些类中知道向后导航不再可能等等。随时准备好应对任何情况都会增加两个数量级的难度。请参见位图:https://dev59.com/G13Va4cB1Zd3GeqPBYzk - kaay

0
这不是一个完整的答案,但我建议您在每个方法中放置toast消息。添加您自己的onPause()onStop()onResume()等,并在内部放置像这样的一行代码:
Toast.makeText(this, "onPause()", Toast.LENGTH_SHORT).show();

您不能直接调用这些方法,但将另一个活动移动到堆栈顶部将导致现有活动上的这些方法被调用。还有一件事需要记住的是,onCreate()不需要每次启动活动时都被调用。这实际上取决于您如何启动活动,例如如果您发送此意图

Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP);

如果已经创建了,它将调用onNewIntent()。总之,最好的方法就是观察Toast消息。此外,您真的需要专注于使用调试器。在每个方法上设置断点,您就可以看到它了。我确定一件事情,那就是您不能直接调用这些方法,比如onPause()。还要记住,通常您不知道何时会调用onDestroy()


2
请原谅我,但我不明白这如何帮助我。我已经更新了描述以澄清我的意思,简而言之:onDestroy与此无关。 我需要了解要准备什么,以及不能发生什么。并非所有内容都可以限制在一个Activity的范围内,例如,我不知道TabActivity中的Activities是如何管理的。 试错已经不是选项,我几乎总是从“一切都活着”跳到“除了进程被销毁的一切”。如何测试其他情况? 另外,为什么我要使用Toast?即使是system.out似乎也是更好的选择。 - kaay
我还想补充一点,关于onPause之后的文档说明“托管活动的进程可能随时被系统杀死,而不执行其代码的另一行”,这是误导性的,单个活动可以与其他所有内容分开销毁。甚至应用程序对象以下的所有内容都可以被销毁,而进程仍然可以存在很长时间。 - kaay

0

关于活动,只有在调用finish()函数之前,它们才会在onDestroy()中被销毁。

片段生命周期完全匹配其父活动,所以当父活动在onDestroy()中被销毁时,片段的onDestroy()也将被调用。

计时器任务会在活动创建它们后完成工作并成为垃圾回收的候选对象。任务在自己的线程中运行,与活动无关,即使活动被销毁,任务也会自行完成....


0
ActivityManagerService#trimApplications()方法会在应用的当前接收器为null,没有任何活动和服务时删除任何未使用的应用程序进程。

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