onSaveInstanceState/onPause - 等到状态完全保存后再允许进程被终止
我正在开发我的第一个 Android 应用程序。它有一个模型,当用户进行更新时,该模型会持久保存到数据库中。
当调用 onSaveInsanceState 时,我想保存一个 id,该 id 可用于从数据库加载用户正在处理的文档。但这只有在文档完全进入数据库后才会发生。在某些情况下,保存一个复杂的文档可能需要几秒钟(我希望一旦我完成所有详细的注销,这会加快速度,并且在实际使用中,用户将分阶段构建一个复杂的文档,每个阶段将被持久化到数据库中,因此复杂的文档不太可能必须一次性全部保存)。
现在,Android 上线程的第一条规则是“不要阻塞 UI 线程”,因此数据库交互当然发生在单独的线程上。但我对Android生命周期的理解是,在很多情况下,onSaveInstanceState被调用是因为Android系统想要杀死进程。这表明我不能允许此方法返回,直到数据库线程完成保存文档(事实上,根据我当前的设计,在将文档保存到数据库之前,我实际上并不知道文档的 id 号是什么,所以我什至不能将其放入保存状态包中)。
在这种情况下,阻塞 UI 线程以等待持久任务完成是否合适?当由于进程被终止而调用 onSaveInstanceState
时,应用程序在前台不再可见,因此不会出现无响应的界面。
但是,当 Activity 实例因配置更新而被废弃(屏幕方向发生变化时)时,也会调用 onSaveInstanceState
。当向侧面旋转屏幕几秒钟后没有任何反应时,这是非常不幸的。在这种情况下,进程(以及内存空间)仍然存在,因此如果我可以在 Bundle 中存储对它的引用而不是其 id,那么我并不严格需要确保文档命中数据库。但我不知道有什么方法可以区分这两种情况。
对于这些情况有公认的做法吗?为了安全起见,我应该阻止线程吗?我可以只使用普通的 Java 线程原语来阻塞和等待吗?我可以做一些事情,不阻塞线程,但确保持久任务将在 Android 关闭进程之前完成?
所有这些也适用于 onPause
,因为 onSaveInstanceState
不一定会被调用。
I'm working on my first Android app. It has a model that is persisted to a database as the user makes updates.
When onSaveInsanceState
is called, I want to save an id that can be used to load the document the user was working on from the database. But this can only happen once the document has fully hit the database. In some cases, persisting a complex document can take several seconds (I'm hoping this will speed up once I take all the verbose logging out, and in actual use a complex document will be built up by the user in stages, each of which will be persisted to the database, so it's not very likely for a complex document to have to all be saved in one go).
Now, the #1 rule of threading on Android is "don't block the UI thread", so of course the DB interactions happen on a separate thread. But my understanding of the Android lifecycle is that in many cases onSaveInstanceState is being called because the Android system wants to kill the process. That suggests I can't allow this method to return until the DB thread finishes saving the document (and in fact with my current design, I don't actually know what the id number of the document is until it's been saved to the DB, so I can't even put that in the bundle of saved state).
Is it appropriate under these circumstances to block the UI thread waiting for the persist task to be done? When onSaveInstanceState
is called because the process is being killed, the app is no longer visible in the foreground, so there's no interface to become unresponsive.
But onSaveInstanceState
is also called when the Activity instance is being trashed by a config update, which happens when the screen orientation changes. It's very unfortunate when rotating the screen sideways fails to do anything for several seconds. In this case the process (and therefore memory space) is still around, so I don't strictly need to ensure the document hits the database, if I can just store a reference to it in the Bundle instead of its id. But I'm not aware of a way to tell the difference between these two cases.
Is there an accepted practice for these situations? Should I just block the thread to be safe? Can I just use normal Java thread primitives to block and wait? Is there something I can do that doesn't block the thread but ensures the persist task will be finished before Android closes the process?
All this also applies to onPause
, as onSaveInstanceState
isn't necessarily going to be called.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您不必在
onSaveInstanceState
中进行持久保存,您几乎可以将实例状态保存在Bundle
中,以便可以在Bundle
中快速恢复实例代码>onRestoreInstanceState。文档指出,您应该将关键的持久数据(例如用户编辑)写入
onPause
中的存储,但它也指出它应该很快,以便下一个活动可以开始执行它想要的任何操作去做。我认为我的建议是仅将文档文本和捆绑包中的任何内容保存在
onSaveInstanceState
中,并在onRestoreInstanceState
中恢复它。使用 onPause 快速保存“备份副本”(也许是临时文件?),如果尚未保存到数据库,则可以在 onResume 中恢复。并使用onStop
(当活动已在后台时调用)将数据实际保存到数据库。请注意,该活动可能会在调用
onPause
后被终止(以前从来没有,除非系统只剩下很少的资源......),这就是为什么我会在尝试提交之前保存一个快速备份在数据库中。编辑 - 基于注释的额外
为了确保正在执行保存过程的后台线程在应用程序被系统杀死之前完成保存,我认为可以阻止并等待保存线程完成,然后再从
onPause
返回,但我建议使用android:configChanges="orientation"
来防止活动重新启动(以及onPause
> 当方向改变时调用)。You don't have to do to the persistent saving in
onSaveInstanceState
, you can pretty much just save the instance state in theBundle
so that the instance can be quickly resumed inonRestoreInstanceState
.The Documentation states that you should write crucial persistent data (such as user edits) to storage in
onPause
, but it also states that it should be fast so that the next activity can start doing whatever it is it wants to do.I think my recommendation here would be to just save the document text and whatever in the Bundle in
onSaveInstanceState
and restore it inonRestoreInstanceState
. UseonPause
to save a "backup copy" somewhere fast (temporary file maybe?) which can then be restored inonResume
if it hasn't been saved to the database. And useonStop
(which is called when the activity is already in the background) to actually save the data to the database.Note that the activity might get killed after
onPause
has been called (never before, unless the system has very very few resources left...), that's why I would save a quick backup before trying to commit it in the database.Edit - Extra based on comments
To make sure the background thread that's doing the saving process is done saving before the application can be killed by the system, I think it's fine to block and wait for the saving thread to complete before returning from
onPause
but I recommend usingandroid:configChanges="orientation"
to prevent activity restart (andonPause
call) when the orientation changes.您应该尝试 AsyncTask,它将阻止您的 ui 但不会显示空白屏幕,将加载必要的 xml 元素,然后从异步任务中获取调用,在异步任务中将您的文档保存在数据库中。
请点击以下链接:AyncTask Exmaple
You should try AsyncTask, which will block your ui but wont show blank screen, will load the necessary xml elements and then will get call from Async task, in async task save your doc in database.
Follow this link: AyncTask Exmaple