在 Android onStop 中完成 ~200 毫秒工作的最可靠方法
Most reliable way to do ~200 ms work in Android onStop
我经常看到 post 说文件写入应该在后台线程中完成,即使应用程序正在关闭时也是如此 (onStop
) -- 即使这项工作对应用
我对此感到困惑。当然 onStop
是一个 UI 电话,其中 Android 应该 ,也许 必须 ,请宽容应用程序完成 关键 工作的时间。
我担心在后台线程上执行 关键 工作,不会 通知 OS 工作很关键,需要完成。
这有几个相关的方面:
----- 困扰我的是什么;我写这个问题的原因-----
- 在允许
onStop
到 return 之后,在后台线程上做关键工作 可靠吗? onStop
的 return 是否向 Android 发出应用程序已完成关键任务的信号,并且应用程序在恢复后将正常运行 即使 android 立即杀死它?
(换句话说,在我看来 [在后台线程中完成关键工作] 的建议是错误的。我试图找到 证据 一种或另一种方式。这就是我写这个问题的原因。)
----- 是否存在任何支持背景方法的证据? -----
证据 如果我听从建议,并在后台线程中完成工作,那么 Android 会认为 运行在决定是否可以终止应用程序时考虑宁线程。 [如果我写的是手机 OS,我不会太重视后台线程的存在。我怀疑大多数复杂的应用程序仍然有后台线程 运行ning。]
证据 将 return 从 onStop
延迟最多 200 毫秒是不好的。
----- 或者有任何证据表明可以在前台执行此操作吗? -----
- 或者相反,证据直接在UI线程中执行它是可以的直到某个合理的时间,并且关于什么时间被认为是合理的证据。
----- 或者大型应用程序编写者做什么? -----
- 证据 关于高下载量、高知名度的应用程序使用的方法。在 onStop 中写入文件时,它们是停留在 UI 线程上,还是在后台执行?或者他们是否使用服务来 100% 确定? [我认为 Android 除非绝对必要,否则不太可能以将这些家伙搞砸的方式进行更改。]
注意:我看到了很多意见。我不需要再听任何意见了。正在寻找 证据。
注意:我对创建一些 Android 将保留 运行ning 的服务或其他解决方案的建议不感兴趣。我不是在谈论足够长的工作来证明这一点。我说的是每个重要的应用程序在被告知要终止时所做的普通工作。
更新:我很欣赏到目前为止两个回复中的信息,但我觉得有一个要点被忽略了:
onStop
和所有其他 UI 回调之间有一个重要区别:
当应用程序从 onStop returns 时,returning 的行为是应用程序向 OS 声明应用程序现在可以安全被杀死。对吧?这不就是onStop的精髓吗?
因此,逻辑上遵循应用程序不应该return在它完成所有关键工作之前return。
(是的,显然应该设计应用程序,以便尽快完成关键工作的完成。但我们不要失去这里的要点。如果你 return,你告诉OS 它现在可以安全地杀死你。如果它确实立即杀死了你,并且你的应用程序状态因为你在未完成的后台线程上完成了该工作而变得混乱,那么你的方法是有缺陷的。是吗?不是吗?我想看看我的分析有什么问题...)
更新#2
在与@CommonsWare 的讨论中(请参阅他的回答下的评论),我了解到 IntentService 可以完成我想要的,并且不需要向用户请求任何额外的权限。
我想到了iOS,对后台工作要求很严格。我相信任何此类方案都需要 iOS 下的额外应用许可。我避免了额外的应用程序权限,以免吓跑任何用户。
因此,作为一名经验丰富的 iOS 应用程序开发人员,但作为一名经验不足的 Android 开发人员,我不知道我需要的答案是:
- 与 iOS、IntentService can be used, WITHOUT ADDING ANOTHER APP PERMISSION, to do background work 不同的是 OS 会继续,即使应用 activity 已终止。
因为 IntentService 会继续 运行ning,而且启动成本不高,也不需要额外的应用程序权限,所以没有 "downside" 使用 IntentService 启动后台工作,允许onStop 立即 return,同时确保完成关键工作。
我已经接受了 CommonsWare 的回答。
更新 #3 根据 @zgc7009 在评论中的问题和我的回复评论,我还应该确保所有关键信息始终被永久存储。请参阅这些评论以了解在 onStop 之前未存储的内容的详细信息,这导致我 post 这个问题。这种不断更新的方法的优势在于,即使应用程序崩溃,它也能提供帮助。
注意:确保用于保存关键信息的机制即使在应用程序消失时仍能完成(对于可靠性)仍然很重要。 [或者至少 "transaction guarantee" 数据不会被中途更改。]
我可能会使用 IntentService 作为实现这一目标的一部分。 (我们的数据已序列化 XML,因此我们的代码需要 运行 直到它完成关键数据的序列化,并刷新并关闭该本地文件。)
无论我们在 Android 中执行什么任务,我们都尽量在 16 毫秒 内完成。
因为目标是达到 60fps 而 1000ms/60 是~16ms。
因此,如果我们希望在主线程 运行 时不跳过任何帧,
我们应该严格遵守这一点。
例如:如果您尝试在主线程中写入Thread.sleep(200);
。您的 logcat 将输出 'x' 帧被跳过,您可能在主线程上做了太多工作。
编辑:如果由于某种原因,您的 main 线程阻塞超过 5 秒,您将被臭名昭著的 ANR(应用无响应)警告!
even when the app is shutting down (onStop)
onStop()
是 Activity
上的一个方法。当 activity 不再可见时将调用它。这可能与应用程序是否 "shutting down" 有任何关系,也可能没有任何关系。例如,从一个 activity 转换到另一个触发 onStop()
,配置更改也是如此(默认情况下)。
Surely onStop is the one UI call where Android should, perhaps must, be lenient in giving the app time to complete critical work.
这不是"leniency"的问题。 onStop()
在主应用程序线程上调用。您在主应用程序线程上所做的任何事情都会绑定该线程,从而阻止 Android 在该线程上进行其他工作。由于 UI 由主应用程序线程驱动,因此在 onStop()
.
占用主应用程序线程期间,您的 UI 将被冻结
请注意,这并非 onStop()
所独有。 任何 占用主应用程序线程的地方都是UI 被冻结的地方。 Android 开发人员采用术语 "jank" 来专门表示此行为。
您可能觉得 200 毫秒的冻结 UI 完全可以接受。其他开发商可能不会。用户可能会也可能不会。
But does that matter, during onStop? During onPause that would be bad, but what about onStop?
在很多情况下,确实如此。仅仅因为 onStop()
activity 不再在前台并不意味着您的活动 none 在前台,除非您只有一个 activity 这不是配置更改。
that Android takes the existence of that running thread into consideration, when deciding whether it is okay to kill the app
它不会,除非该线程由 Service
管理(在这种情况下,Android 会考虑 Service
,而不是线程)。
为了扭转局势,我对任何 证据 都非常感兴趣 Android 将在 onStop()
的约 200 毫秒内终止您的进程被调用。否则,您的线程将 运行 顺利完成。
I am specifically interested in the failure of the docs I've seen to discuss the different nature of onStop
那是因为onStop()
在其他人眼中并没有什么不同。欢迎您相信它是不同的,但请不要指望其他人 "retcon" 已经写过的关于 Android 应用程序开发的内容来适应您的世界观。
Evidence that it is bad to delay the return from onStop by up to 200 ms.
"Bad"是主观描述。可以说明的是:
onStop()
在主应用程序线程上被调用(为了证明这一点,记录线程 ID)
占用主应用程序线程会阻止在该线程上完成其他工作(线程运行的基础)
~200ms 是 ~12 帧 60fps(长除法)
When an app returns from onStop, the act of returning is a statement from the app to the OS that the app can now be safely killed.
"app" 不会 return 来自 onStop()
。 onStop()
是 Activity
上的一个方法。一个应用程序可能有零个、一个或多个活动。 onStop()
与移动到后台的应用程序松散相关,但 onStop()
也会在其他情况下被调用,如前文所述。
If you return, you are telling the OS it can now safely kill you
您假设从 onStop()
到 return 失败将使您的进程永远存在。 onStop()
是一个咨询事件,告诉你"hey, your activity has moved to the background"。你从 onStop()
中 return 的速度对于负责终止进程以释放系统 RAM 的 OS 进程来说并不重要。
我经常看到 post 说文件写入应该在后台线程中完成,即使应用程序正在关闭时也是如此 (onStop
) -- 即使这项工作对应用
我对此感到困惑。当然 onStop
是一个 UI 电话,其中 Android 应该 ,也许 必须 ,请宽容应用程序完成 关键 工作的时间。
我担心在后台线程上执行 关键 工作,不会 通知 OS 工作很关键,需要完成。
这有几个相关的方面:
----- 困扰我的是什么;我写这个问题的原因-----
- 在允许
onStop
到 return 之后,在后台线程上做关键工作 可靠吗?onStop
的 return 是否向 Android 发出应用程序已完成关键任务的信号,并且应用程序在恢复后将正常运行 即使 android 立即杀死它?
(换句话说,在我看来 [在后台线程中完成关键工作] 的建议是错误的。我试图找到 证据 一种或另一种方式。这就是我写这个问题的原因。)
----- 是否存在任何支持背景方法的证据? -----
证据 如果我听从建议,并在后台线程中完成工作,那么 Android 会认为 运行在决定是否可以终止应用程序时考虑宁线程。 [如果我写的是手机 OS,我不会太重视后台线程的存在。我怀疑大多数复杂的应用程序仍然有后台线程 运行ning。]
证据 将 return 从
onStop
延迟最多 200 毫秒是不好的。
----- 或者有任何证据表明可以在前台执行此操作吗? -----
- 或者相反,证据直接在UI线程中执行它是可以的直到某个合理的时间,并且关于什么时间被认为是合理的证据。
----- 或者大型应用程序编写者做什么? -----
- 证据 关于高下载量、高知名度的应用程序使用的方法。在 onStop 中写入文件时,它们是停留在 UI 线程上,还是在后台执行?或者他们是否使用服务来 100% 确定? [我认为 Android 除非绝对必要,否则不太可能以将这些家伙搞砸的方式进行更改。]
注意:我看到了很多意见。我不需要再听任何意见了。正在寻找 证据。
注意:我对创建一些 Android 将保留 运行ning 的服务或其他解决方案的建议不感兴趣。我不是在谈论足够长的工作来证明这一点。我说的是每个重要的应用程序在被告知要终止时所做的普通工作。
更新:我很欣赏到目前为止两个回复中的信息,但我觉得有一个要点被忽略了:
onStop
和所有其他 UI 回调之间有一个重要区别:
当应用程序从 onStop returns 时,returning 的行为是应用程序向 OS 声明应用程序现在可以安全被杀死。对吧?这不就是onStop的精髓吗?
因此,逻辑上遵循应用程序不应该return在它完成所有关键工作之前return。
(是的,显然应该设计应用程序,以便尽快完成关键工作的完成。但我们不要失去这里的要点。如果你 return,你告诉OS 它现在可以安全地杀死你。如果它确实立即杀死了你,并且你的应用程序状态因为你在未完成的后台线程上完成了该工作而变得混乱,那么你的方法是有缺陷的。是吗?不是吗?我想看看我的分析有什么问题...)
更新#2 在与@CommonsWare 的讨论中(请参阅他的回答下的评论),我了解到 IntentService 可以完成我想要的,并且不需要向用户请求任何额外的权限。
我想到了iOS,对后台工作要求很严格。我相信任何此类方案都需要 iOS 下的额外应用许可。我避免了额外的应用程序权限,以免吓跑任何用户。
因此,作为一名经验丰富的 iOS 应用程序开发人员,但作为一名经验不足的 Android 开发人员,我不知道我需要的答案是:
- 与 iOS、IntentService can be used, WITHOUT ADDING ANOTHER APP PERMISSION, to do background work 不同的是 OS 会继续,即使应用 activity 已终止。
因为 IntentService 会继续 运行ning,而且启动成本不高,也不需要额外的应用程序权限,所以没有 "downside" 使用 IntentService 启动后台工作,允许onStop 立即 return,同时确保完成关键工作。
我已经接受了 CommonsWare 的回答。
更新 #3 根据 @zgc7009 在评论中的问题和我的回复评论,我还应该确保所有关键信息始终被永久存储。请参阅这些评论以了解在 onStop 之前未存储的内容的详细信息,这导致我 post 这个问题。这种不断更新的方法的优势在于,即使应用程序崩溃,它也能提供帮助。
注意:确保用于保存关键信息的机制即使在应用程序消失时仍能完成(对于可靠性)仍然很重要。 [或者至少 "transaction guarantee" 数据不会被中途更改。] 我可能会使用 IntentService 作为实现这一目标的一部分。 (我们的数据已序列化 XML,因此我们的代码需要 运行 直到它完成关键数据的序列化,并刷新并关闭该本地文件。)
无论我们在 Android 中执行什么任务,我们都尽量在 16 毫秒 内完成。
因为目标是达到 60fps 而 1000ms/60 是~16ms。
因此,如果我们希望在主线程 运行 时不跳过任何帧, 我们应该严格遵守这一点。
例如:如果您尝试在主线程中写入Thread.sleep(200);
。您的 logcat 将输出 'x' 帧被跳过,您可能在主线程上做了太多工作。
编辑:如果由于某种原因,您的 main 线程阻塞超过 5 秒,您将被臭名昭著的 ANR(应用无响应)警告!
even when the app is shutting down (onStop)
onStop()
是 Activity
上的一个方法。当 activity 不再可见时将调用它。这可能与应用程序是否 "shutting down" 有任何关系,也可能没有任何关系。例如,从一个 activity 转换到另一个触发 onStop()
,配置更改也是如此(默认情况下)。
Surely onStop is the one UI call where Android should, perhaps must, be lenient in giving the app time to complete critical work.
这不是"leniency"的问题。 onStop()
在主应用程序线程上调用。您在主应用程序线程上所做的任何事情都会绑定该线程,从而阻止 Android 在该线程上进行其他工作。由于 UI 由主应用程序线程驱动,因此在 onStop()
.
请注意,这并非 onStop()
所独有。 任何 占用主应用程序线程的地方都是UI 被冻结的地方。 Android 开发人员采用术语 "jank" 来专门表示此行为。
您可能觉得 200 毫秒的冻结 UI 完全可以接受。其他开发商可能不会。用户可能会也可能不会。
But does that matter, during onStop? During onPause that would be bad, but what about onStop?
在很多情况下,确实如此。仅仅因为 onStop()
activity 不再在前台并不意味着您的活动 none 在前台,除非您只有一个 activity 这不是配置更改。
that Android takes the existence of that running thread into consideration, when deciding whether it is okay to kill the app
它不会,除非该线程由 Service
管理(在这种情况下,Android 会考虑 Service
,而不是线程)。
为了扭转局势,我对任何 证据 都非常感兴趣 Android 将在 onStop()
的约 200 毫秒内终止您的进程被调用。否则,您的线程将 运行 顺利完成。
I am specifically interested in the failure of the docs I've seen to discuss the different nature of onStop
那是因为onStop()
在其他人眼中并没有什么不同。欢迎您相信它是不同的,但请不要指望其他人 "retcon" 已经写过的关于 Android 应用程序开发的内容来适应您的世界观。
Evidence that it is bad to delay the return from onStop by up to 200 ms.
"Bad"是主观描述。可以说明的是:
onStop()
在主应用程序线程上被调用(为了证明这一点,记录线程 ID)占用主应用程序线程会阻止在该线程上完成其他工作(线程运行的基础)
~200ms 是 ~12 帧 60fps(长除法)
When an app returns from onStop, the act of returning is a statement from the app to the OS that the app can now be safely killed.
"app" 不会 return 来自 onStop()
。 onStop()
是 Activity
上的一个方法。一个应用程序可能有零个、一个或多个活动。 onStop()
与移动到后台的应用程序松散相关,但 onStop()
也会在其他情况下被调用,如前文所述。
If you return, you are telling the OS it can now safely kill you
您假设从 onStop()
到 return 失败将使您的进程永远存在。 onStop()
是一个咨询事件,告诉你"hey, your activity has moved to the background"。你从 onStop()
中 return 的速度对于负责终止进程以释放系统 RAM 的 OS 进程来说并不重要。