【问题标题】:Is System.exit(0) really that dangerous?System.exit(0) 真的那么危险吗?
【发布时间】:2013-09-06 12:32:15
【问题描述】:

应用程序后台服务更新 sqlite 数据库。因此,我的活动变得过时了。活动意图还包含过时的参数,因此 onCreate、onResume 将使应用程序崩溃。一个最简单的解决方案是重新启动整个应用程序。我不想为所有活动中的所有 onCreate、onResume 方法添加 IF 来处理一种特殊情况。

我注意到ACRA 在处理异常后执行了以下代码。

android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);

但是,许多人不鼓励使用System.exit(0)System.exit(0) 对 Android 应用程序数据完整性真的那么危险吗?当然我的代码会在数据库存在之前关闭数据库。

更新:

我知道如何使用finish()、内容提供者、发送广播、在 SO 上阅读许多答案等。但是,这些方法中的每一种都需要额外的数千行代码。我在十分钟内用System.exit(0) 实现了解决方案。重启太快了,和普通的 startActivity 动作没有区别。数据库更新/重启是在用户长时间不活动后完成的,因此应用程序已经被系统挂起。我的应用不需要实时同步。在测试期间,应用程序行为正确。这是一个快速而肮脏的解决方案。

因此我问了关于System.exit(0) 可能产生的副作用的问题。不是我如何以不同的方式进行设计。我知道目前的设计并不完美。

【问题讨论】:

标签: android application-restart


【解决方案1】:

System.exit(0) 是来自Java 运行时的工件,它不适用于Android。所以在任何情况下使用它都是最糟糕的解决方案。

你为什么不优雅地使用Activity.finish()

如果你终止你所在的进程,你将失去大部分的缓存和重启时间(~在用户的眼中恢复),因为下一次它会更长。

Activity Lifecycle documentation on Android Developers阅读更多内容。

【讨论】:

  • 不是我,但我相信这是因为 OP 想要一种机制来在活动实例未知时关闭活动。可以说,该活动可以处理广播并被标记为关闭,但其基础设施都是错误的。
  • @Gusdor 所以你认为答案应该是“不,它不会烧手机”吗? :)
  • 因为finish() 的解决方案需要向所有活动添加许多if 语句。请阅读问题下方的其他 cmets。
【解决方案2】:

杀死进程不会从进程外清除任何已注册的资源。例如,广播接收器。这是泄漏,设备会告诉您很多信息。

您真的不应该从后台服务更新数据库schema。当您的活动恢复时执行此操作。

如果您只是更新数据,恢复活动应该验证 Intent 指定的数据并告诉用户,例如,项目 X 是否不再存在。

【讨论】:

    【解决方案3】:

    如果小心使用并用于特定的、经过深思熟虑的目的,任何工具都不会那么危险。

    但是,就您而言,我不认为System.exit() 是正确的方法。如果您的应用程序依赖于数据库中的数据,请创建一个后台服务(或几个,取决于您的需要),它将通知您的应用程序更改并更新数据。在我看来,这是处理变更的正确方式。

    至于你想使用System.exit() 的场景,我个人有时会在我无法从严重错误中恢复并且不可能优雅降级时使用它。在这些情况下,最好强制停止与您的应用程序相关的所有资源,而不是让松散的东西纠缠在一起。澄清一下,在做任何激进的事情之前,您应该始终使用错误处理。正确的错误处理通常是要走的路。

    但这是一个非常微妙的话题,您可能会收到很多不同的答案。

    【讨论】:

    • 当然,同样的原因也适用于 System.exit(),也适用于任意杀死线程。清理。
    • Cleanup 不会任意杀死线程,至少不应该。它应该根据一组参数(例如内存使用情况和活动​​)来选择线程。当然,在某些情况下,最好的选择可能是随机选择。但即便如此,这个决定也应该是谨慎而有目的的。我想底线是你永远不应该使用System.exit(),因为你很懒惰或者把自己设计成一个不可能的情况。
    【解决方案4】:

    因此我的活动已经过时了。

    使用ContentProviderContentObserver(或Loader 框架),或使用消息总线(LocalBroadcastManager、Otto 等)就地更新活动

    Activity Intent 还包含过时的参数,因此 onCreate、onResume 会使应用程序崩溃

    将相关的“参数”复制到活动的数据成员。根据需要更新这些数据成员(例如,从消息总线引发的事件的处理程序中)。保留该数据作为您的实例状态的一部分以进行配置更改(例如,onSaveInstanceState())。使用来自onCreate()onResume() 等的数据。

    最简单的解决方案是重新启动整个应用程序

    如果您重视您的用户,这并不容易,因为您的用户不会欣赏您在使用时自发消失的应用程序。您是否认为 Gmail 每次收到电子邮件时都会崩溃自己的应用程序?

    接下来,您将建议编写一个 Web 应用程序,该应用程序使用一些漏洞来使浏览器崩溃,因为您不知道如何更新网页。

    我注意到 ACRA 在处理异常后执行了以下代码。

    顶级异常处理程序是拥有此类代码的唯一合理位置,即使在那里,目标也是使该代码永远不会运行(即,没有未处理的异常)。

    【讨论】:

    • 请阅读问题更新。我的竞争对手都没有实时或后台更新。因为它们不是必需的。这些是我必须关注的其他更重要的功能。
    • @GregDan:“然而,这些方法中的每一种都需要额外的数千行代码”——这应该为每个使用数据库的活动/片段添加几十行,再加上几行在进行更新时。如果您有一个包含数百个活动/片段的应用程序,那么您还有其他问题。
    【解决方案5】:

    有一个现有的答案HERE 可能会帮助您了解为什么人们说使用 System.Exit() 不好。

    【讨论】:

    • 请不要只发布链接答案。
    • 对不起,我不知道这是不受欢迎的。
    • 没关系。通常,您希望将仅链接的内容作为 cmets 发布或将其用作补充。我们不希望答案因为链接失效而失去相关性。
    猜你喜欢
    • 1970-01-01
    • 2015-07-25
    • 2015-03-08
    • 2011-12-31
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    相关资源
    最近更新 更多