问题 何时将数据保存到数据库,onPause()或onStop()?


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

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

根据 表1中的Android开发人员指南

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

Killable:是的

然后根据 类似表中的Android Developer Reference Guide

它说同样的事情但是:

Killable:Pre-HONEYCOMB

他们添加了一个说明:

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


Killable

请注意上表中的“Killable”列 - 对于那些标记为可填充的方法,  该方法返回托管活动的进程可能在任何时候被系统杀死而不执行其代码的另一行。

对于POST-HONEYCOMB(我不关心早期版本): 那么,可以假设任何Android设备(包括不同的ROMS)都能确保在活动上调用onStop吗?这是任何时间消耗存储写入应用程序的最佳位置?

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


11508
2018-04-06 22:43


起源

看到 developer.android.com/about/dashboards/index.html 用于当前设备分发。截至2015年4月,预蜂窝设备仅占7.5%,因此为了保持逻辑更简单,您可能希望定位API 15+并忽略旧行为。或者只是全力以赴 onPause() 并称它为一天。 - fadden
fadden,这个评论根本没有帮助 - klifa
感谢您澄清您实际上对蜂窝前行为不感兴趣。 - fadden
我讨厌这个问题,原因是我在近7到10个安卓面试中看到这个问题作为一个多项选择问题而且出人意料的是MCQ包含 a) onStop() b) onPause() c) onDestroy() d) onActivityKill() 选项。答案应该是什么? - Piyush Kukadiya


答案:


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

无论是。它们几乎完全相同,特别是在Android 3.0+上。

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

如果接管前景的活动主题更像是对话框,之前的活动仍然可见, onPause() 将被召唤,但不是 onStop(),直到活动不再可见为止(例如,用户现在按下HOME)。

在这种情况下,大多数应用程序并不担心“主题更像是对话”场景 onPause() 和 onStop() 在下一个之后被称为一个,你可以分叉你的后台线程来保存你的数据中的任何一个。

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

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

那么,可以假设任何Android设备(包括不同的ROMS)都能确保在活动上调用onStop吗?

onPause() 和 onStop() 从过程终止的角度来看,它们具有相同的特性。两者都应该被调用(正常情况)或两者都不会被调用(例如,你崩溃,电池弹出电话背面)。

这是任何时间消耗存储写入应用程序的最佳位置?

onPause() 要么 onStop() 是一个很好的地方来触发工作,在后台线程上完成,以保持您的数据。如果你喜欢这样做的话 onStop(),绝对欢迎你这样做。就个人而言,我是一个 onPause() 那种人。


15
2018-04-07 16:24



如果这是一个耗时的操作或任何操作,你只想做一次或尽可能少的操作,最好在onStop()中执行它,因为它具有完全相同的结果,并且它将被更频繁地调用吗? - klifa
对于任何在何时寻找信息的人 onPause() 和 onStop() 是 不 “几乎相同”,见 developer.android.com/guide/components/...。换句话说:“当从一个活动转换到另一个活动时,第一个活动在创建第二个活动之前没有完全停止”。 - Vicky Chijwani
@VickyChijwani:从问题中讨论的内容来看,它们几乎完全相同。 - CommonsWare
@CommonsWare你是对的,我只是为感兴趣的人添加更多信息。 - Vicky Chijwani
@CommonsWare - 但不是重点 onPause 它 是 打电话给 一些 情况在哪里 onStop 不叫?因此官方声明如“你应该避免在onPause()期间执行CPU密集型工作,例如写入数据库,因为它可以减慢到下一个活动的可见转换(你应该在onStop期间执行重载关闭操作) )“。 developer.android.com/training/basics/activity-lifecycle/... - ToolmakerSteve


  • 如果您想要更安全,请存放 onPause
  • 如果您的数据太大而无法将其存储几秒钟,则可以打开背景 Service (例如。 IntentService)保存。
  • 您还可以在代码中检查系统版本,并选择保存的时间。 if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.ICE_CREAM_SANDWICH){}
  • 在大多数情况下,这个保存时间的规则不会被某些定制的操作系统更改。但当然可能还有其他一些操作系统肯定会改变它。因此,Android开发中最重要的事情是你需要知道不同手机中的一切都会有所不同。

0
2018-04-06 22:48



谢谢你的回答,IntentService可能是个好主意。但是,对于蜂窝后的设备(编辑我的问题),同样的问题仍然存在。为什么在onPause中“更安全”,在onStop中执行它也是安全的,另外,因为它不会阻止UI我不需要使用后台服务来保存数据吗? - klifa
@klifa:两个 onPause() 和 onStop() 在主应用程序线程上调用。在任何一种情况下,您都需要使用后台线程。是否使用的区别 IntentService 而平原 Thread 主要是在你的I / O需要的时候。如果它将超过一秒左右,我会使用 IntentService,所以有一个信号告诉Android你的进程仍然在工作,即使是 onPause() 要么 onStop() 由您的应用移动到后台触发,有资格终止。 - CommonsWare
@CommonsWare - 你能提供任何链接或证据表明有必要在后台线程上进行工作吗? onStop,如果工作可能达到200毫秒?或者,在决定终止您的应用程序是否安全时,操作系统会考虑运行后台线程的任何证据?我一直在OnStop的前台做一些文件写入,以确保它已经完成。 - ToolmakerSteve
@ToolmakerSteve:“你可以提供任何链接或证据表明有必要在后台线程上进行工作,对于onStop,如果工作时间大约可能超过200毫秒吗?” - 你应该在框架的任何回调上花费<1ms,以避免jank。 〜200ms将以60fps的速度下降~12帧。 StrictMode例如,将指出主应用程序线程上的磁盘I / O是不合适的,并且自API级别9以来已经这样做了。 - CommonsWare
@ToolmakerSteve:“当决定终止你的应用程序是否安全时,操作系统会考虑运行后台线程的任何证据?” - 它不会。但是,您的应用程序只是退出前台,因此它的进程不太可能在接下来的200ms内终止。如果您对此感到担心,请使用 IntentService 而不是一个简单的线程。通常情况下,直到接近1000毫秒大关,我才会达到这个程度。 - CommonsWare