一个Android服务是否保证会调用onDestroy()方法?

63
在Android上,Activity的生命周期图表不能保证一定会调用onDestroy()方法,但可能会杀死进程并突然删除Activity。而Service的生命周期图表可以保证一定会调用onDestroy()方法。所以我有两个关于这种差异的问题。
首先,如果Service是与Activity相同的进程的一部分,那么即使Activity的onDestroy()方法没有被调用,Service的onDestroy()方法也会被调用吗?我认为不会,因为“杀死进程”意味着操作系统停止其线程并释放其资源。
如果是这种情况,操作系统能否突然杀死仅包含Service的进程呢?
2个回答

38

我不确定您在哪里看到了一个Service一定会调用onDestroy()的保证。据我所知,情况并非如此。如果您阅读文档中的这一页,它描述了服务可能被杀死的条件。因此,如果您问的是一个同时托管活动和服务的进程正在被杀死时,服务(但不是活动)是否会调用onDestroy(),那么答案是否定的;服务的onDestroy()不一定会被调用。至于只有服务的进程是否可以被操作系统突然杀死:是的,它可以。尤其是当您有大量工作要做,并且您的onStartCommand调用仅将工作异步排队时。那么服务将花费大部分时间不在受保护的onCreateonStartCommandonDestroy方法中。


1
那么,当您需要在关闭服务之前清理服务时,如何获得通知呢?例如,我想缓存一些状态并在关闭之前将其刷新到存储中;如果我从未被告知正在关闭,我将失去我的状态 - 这不好! - Michael
1
@Michael 考虑定期/每当数据更改时将其刷新到存储中。这是一个合理的问题。实际上,如果我的简单答案不能满足您,那么发表自己的问题以获得一些深入的答案是值得的。 - kabuko
@kabuko:不,了解这一点确实很好。我最初阅读文档的理解是onDestroy会被调用,所以我决定在状态更改时不进行刷新,以节省电池和闪存擦除次数,但是...那个想法破灭了。我已经决定将我的状态分成两部分,较少更改的部分(<20次/天)存储到内部闪存中,而更频繁的部分(高达1 Hz)存储到可根据需要交换的外部闪存中。尽管如此,我仍然对电池问题感到不满意。 - Michael
因此,如果您正在问一个同时托管活动和服务的进程是否被终止时,服务的onDestroy()方法会被调用(但活动不会),那么答案是否定的。服务的onDestroy()方法不一定会被调用。这是如何知道的?这些信息在哪里记录? - Marian Paździoch
@MarianPaździoch 我不知道这是否有记录,但我向您保证确实发生了这种情况 - onDestroy 没有被调用。 - Dmitry Zaytsev
显示剩余2条评论

14

需要考虑两个问题:

  1. 当内存不足并被其他更紧急的进程所需时,Android可能会决定在某个点关闭进程。因此,在被杀死的进程中运行的应用程序组件也会被销毁。当它们再次有任务要执行时,将为这些组件启动一个新进程。来源

    在这种情况下,onDestroy()不会被调用,因为Android操作系统总体上都会回收资源。

  2. 一个服务可以同时被启动和绑定。在这种情况下,只要服务已经被启动或者存在一个或多个使用Context.BIND_AUTO_CREATE标志连接到它的连接,系统就会保持服务运行。一旦不再满足这些情况之一,服务的onDestroy()方法就会被调用,服务也会被有效地终止。所有清理工作(停止线程,注销接收器)都应该在从onDestroy()返回时完成。来源

    所以,当Android操作系统注意到服务已经完成任务并且不再需要时,它将被销毁。操作系统给应用程序一个机会来释放服务的资源,以防止内存泄漏。在这种情况下, onDestroy()会被调用,因为这是应用程序可以释放资源的地方。当然,在这种情况下,应用程序的进程保持不变(因为可能还有其他正在其中运行的服务/活动)。


那么?这个评论是关于什么的?你引用了官方文档的一部分,那又怎样? - Marian Paździoch
抱歉,我的意思是:“即使这两种情况都存在,服务仍然可能会被杀死,而不调用onDestroy方法。” - Dmitry Zaytsev
什么意思?它的意思是:当服务停止并且没有使用Context.BIND_AUTO_CREATE标志的“更多连接”时,onDestroy将被调用。 - Marian Paździoch
1
是的,在正常情况下(例如通过stopSelf)停止Service时会调用它。但是当系统杀死Service时,并不总是会调用它。 - Dmitry Zaytsev
2
我认为你做错了什么,因为我从未遇到过这样的行为 - Android 要么杀死整个进程(你不必担心任何事情,因为所有资源都会被回收),要么销毁服务(并调用其 onDestroy() 方法 - 你必须自己释放资源,因为进程仍在运行)。如果它不是这样工作的话,那就没有意义了,因为没有人能释放资源,这将导致内存泄漏。荒谬! - Marian Paździoch
显示剩余7条评论

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