【问题标题】:When to save data to database, onPause() or onStop()?何时将数据保存到数据库,onPause() 或 onStop()?
【发布时间】:2015-06-11 10:02:27
【问题描述】:

我知道这个问题已经被问过一百万次了,尽管我自己已经知道答案并且正确的答案是唯一有保证的调用是 onPause(),所以你应该把你的数据保存在那里。

然而,在许多 android 文档的地方,他们总是建议不要在 onPause() 方法中做繁重的工作(例如在数据库中写入数据),因为它会延迟活动之间的转换。

根据Android Developer Guide in Table 1

onPause():此方法通常用于提交对持久数据的未保存更改、停止动画和其他可能消耗 CPU 的事情等。它应该很快地完成它所做的任何事情,因为下一个活动在它返回之前不会恢复。

可杀:是

然后根据Android Developer Reference Guide in the similar table.

它说了同样的话,但是:

可杀:预蜂巢

他们添加了一个小注释,上面写着:

请注意,针对以 HONEYCOMB 开头的平台的应用程序与针对先前平台的应用程序之间的这些语义会略有不同。 从 Honeycomb 开始,应用程序在其 onStop() 返回之前不会处于可终止状态。这会影响何时可以调用 onSaveInstanceState(Bundle)(它可以在 onPause() 之后安全调用,并允许应用程序安全地等待 onStop() 以保存持久状态。


可杀

请注意上表中的“Killable”列——对于那些被标记为可杀死的方法,该方法返回承载活动的进程之后,系统可能随时终止它的另一行代码正在执行。

对于 POST-HONEYCOMB(我不关心早期版本): 那么,可以假设任何 Android 设备(包括不同的 ROMS)都会确保在活动上调用 onStop 吗?而这里是进行任何耗时的 App 存储写入的最佳场所吗?

注意:这非常令人困惑,因为这里的大多数答案、网站、书籍甚至在线 android 测试都将其作为正确答案,您应该将其保存在 onPause 而不是 onStop 中。

【问题讨论】:

  • 请参阅developer.android.com/about/dashboards/index.html 了解当前的设备分布情况。截至 2015 年 4 月,预蜂窝设备仅占 7.5%,因此为了保持逻辑更简单,您可能希望以 API 15+ 为目标并忽略较旧的行为。或者只是在onPause() 中完成所有操作,然后收工。
  • fadden,这条评论根本没有帮助
  • 感谢您澄清您实际上对蜂窝前的行为并不感兴趣。
  • 我讨厌这个问题,原因是我在近 7 到 10 次安卓面试中看到这个问题是一个多项选择题,令人惊讶的是 MCQ 包含a) onStop() b) onPause() c) onDestroy() d) onActivityKill() options。答案应该是什么?

标签: android android-activity android-lifecycle android-database


【解决方案1】:

何时将数据保存到数据库,onPause() 还是 onStop()?

要么。它们几乎相同,尤其是在 Android 3.0+ 上。

如果接管前台的 Activity 是典型的全屏 Activity,那么之前的 Activity 不再可见,onPause()onStop() 将被快速连续调用。

如果接管前台的 Activity 主题更像一个对话框,其中早期的 Activity 仍然可见,则将调用 onPause(),但不会调用 onStop(),直到 Activity 为 no更长的可见性(例如,用户现在按 HOME)。

大多数应用程序并不担心“主题更像一个对话”场景,在这种情况下,onPause()onStop() 会被一个接一个地调用,您可以分叉您的后台线程来保存您的任何对您有意义的数据。

然而,在许多 android 文档的地方,他们总是建议不要在 onPause() 方法中做繁重的工作(例如在数据库中写入数据),因为它会延迟活动之间的转换。

onStop() 也是如此,因为这两个方法都在主应用程序线程上调用。

那么,是否可以假设任何 Android 设备(包括不同的 ROMS)都会确保在 Activity 上调用 onStop?

从进程终止的角度来看,onPause()onStop() 将具有相同的特征。要么都应该调用(正常情况),要么都不调用(例如,你崩溃了,电池从手机背面弹出)。

而这是进行任何耗时的 App 存储写入的最佳场所?

onPause()onStop() 都是触发工作的好地方,在后台线程上完成,以保存数据。如果您更喜欢在onStop() 中完成这项工作,我们绝对欢迎您这样做。就个人而言,我是onPause() 类型的人。

【讨论】:

  • 如果这是一个耗时的操作,或者您只想执行一次或尽可能少的任何操作,最好在 onStop() 中执行它,因为它具有完全相同的结果并且它调用频率会降低吗?
  • 对于任何想了解onPause()onStop() 何时“几乎相同”的信息的人,请参阅developer.android.com/guide/components/…。套用一句:“从一个活动过渡到另一个活动时,第一个活动在创建第二个活动之前并未完全停止”。
  • @VickyChijwani:从问题讨论的角度来看,它们几乎相同。
  • @CommonsWare 你说得对,我只是为感兴趣的人添加更多信息。
  • @CommonsWare - 但onPause 的重点不是在一些 没有调用onStop 的情况下调用它吗?因此,官方声明如“您应该避免在 onPause() 期间执行 CPU 密集型工作,例如写入数据库,因为它会减慢到下一个活动的可见转换(您应该在 onStop() 期间执行重负载关闭操作) )。” developer.android.com/training/basics/activity-lifecycle/…
【解决方案2】:
  • 如果您想要更安全,请存储在onPause
  • 如果您的数据太大以至于需要存储几秒钟,您可以打开后台Service(例如IntentService)进行保存。
  • 您还可以在代码中检查系统版本并选择何时保存。 if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.ICE_CREAM_SANDWICH){}
  • 在大多数情况下,某些自定义操作系统不会更改此保存时间的规则。但是当然可以有一些其他的操作系统肯定会改变它。所以在安卓开发中最重要的是你需要知道在不同的手机上一切都可能不同。

【讨论】:

  • 感谢您的回答,IntentService 可能是个好主意。但是,对于蜂窝后的设备(编辑我的问题),同样的问题仍然存在。为什么在 onPause 中执行它“更安全”,在 onStop 中执行它也很安全,而且由于它不会阻塞 UI,我不需要使用后台服务来保存数据吗?
  • @klifa:onPause()onStop() 都在主应用程序线程上调用。无论哪种情况,您都需要使用后台线程。是否使用IntentService 与普通Thread 的区别主要在于您的I/O 花费的时间。如果超过一秒左右,我会使用IntentService,因此即使onPause()onStop() 正在由您的应用程序触发,Android 也会发出信号表明您的进程仍在工作移动到后台,它有资格被终止。
  • @CommonsWare - 你能否提供任何链接或证据证明有必要在后台线程上完成工作,对于onStop,如果工作可能长达 200 毫秒?或者,在决定终止您的应用程序是否安全时,操作系统会考虑是否有任何证据表明正在运行后台线程?我一直在前台的 OnStop 中进行一些文件写入,以确保它已完成。
  • @ToolmakerSteve:“你能否提供任何链接或证据证明有必要在后台线程上完成工作,对于 onStop,如果工作可能达到 200 毫秒?” -- 你应该在框架的任何回调上花费 ~200ms will drop ~12 frames at 60fps。例如,StrictMode 会指出主应用程序线程上的磁盘 I/O 是不合适的,并且从 API 级别 9 开始就这样做了。
  • @ToolmakerSteve:“在决定终止您的应用程序是否安全时,操作系统将考虑运行后台线程的任何证据?” ——不会的。但是,您的应用程序只是刚刚退出前台,因此它的进程不太可能在接下来的 200 毫秒内终止。如果您对此感到担忧,请使用IntentService 而不是普通线程。通常,在接近 1000 毫秒标记之前,我不会达到那种程度的担忧。
【解决方案3】:

我知道这个问题是史前问题,但像我这样的人似乎仍然碰巧遇到这个问题。所以我想添加一个我在文档中找到的答案可能是有意义的,其中指出:

要保存持久性数据,例如用户偏好或数据库数据,您应该在活动处于前台时抓住适当的机会。如果没有这样的机会出现,您应该在 onStop() 方法期间保存这些数据

source

但是等等,还有更多:

请注意上表中的“Killable”列——对于那些被标记为可终止的方法,在该方法返回后,托管该活动的进程可能随时被系统终止,而无需另一行代码执行。因此,您应该使用 onPause() 方法将任何持久性数据(例如用户编辑)写入存储

source

总结一下,似乎在 onPause() 上持久化数据是最好的做法。

【讨论】:

  • +1 ,进一步阅读,您会发现“......这些语义将在针对平台的应用程序之间略有变化......使用 Honeycomb,应用程序在其 onStop 之前不会处于可终止状态已经回来了”。但是,我同意你保存在 onPause() 中。我在 onPause() 期间保存的原因与活动之间的持久数据共享有关。如果保存在 onStop() 中,持久数据将变得不同步,因为第二个 Activity 在第一个 Activity 的 onStop() 之前启动。
猜你喜欢
  • 1970-01-01
  • 2021-09-30
  • 2013-02-02
  • 2017-07-30
  • 1970-01-01
  • 2017-10-25
  • 2012-03-27
  • 2019-11-22
  • 1970-01-01
相关资源
最近更新 更多