java 离开 Activity 时,Android 如何处理后台线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3898447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:53:59  来源:igfitidea点击:

How does Android handle background threads when leaving an Activity?

javaandroidmultithreadingmobile

提问by memcom

I need my Android app to save it's state to disk when its activity is put in the background or killed. It's been suggested that I start a thread when onPause() is called and perform any expensive I/O procedures there (see Saving/loading document state quickly and robustly for image editor).

我需要我的 Android 应用程序在其活动被置于后台或被终止时将其状态保存到磁盘。有人建议我在调用 onPause() 时启动一个线程并在那里执行任何昂贵的 I/O 过程(请参阅图像编辑器的快速和稳健地保存/加载文档状态)。

In what situations will the OS kill the thread and how commonly do these situations occur?

在什么情况下操作系统会终止线程,这些情况发生的频率如何?

I assume it will be like how Activities are dealt with where the OS can arbitrary decide to kill the thread but will mostly only do this when resources are extremely limited. It would be nice to find some specific documentation of this though.

我认为这就像如何处理活动一样,操作系统可以任意决定终止线程,但大多数情况下只会在资源极其有限的情况下执行此操作。不过,最好能找到一些关于此的特定文档。

From playing around, with some test code, a background thread started in onPause() will run indefinitely in the background on my device (I tried loading lots of apps and couldn't get it to be killed).

通过使用一些测试代码,在 onPause() 中启动的后台线程将在我的设备的后台无限期运行(我尝试加载大量应用程序,但无法将其杀死)。

For my specific app, I'm writing a bitmap editor where I'm using the Command pattern and the Memento pattern to allow undo and redo of edits. I'd like the user to be able to undo/redo their edits even e.g. the user gets a phone call and the activity is killed when it is put in the background. The best solution I can think of is to use a background thread to constantly save my command and memento objects to disk during application use and to finish up saving any objects that are left in a background thread if onPause is called. In the worse case, if the thread is killed I'll only lose some edits.

对于我的特定应用程序,我正在编写一个位图编辑器,我在其中使用命令模式和备忘录模式来允许撤消和重做编辑。我希望用户能够撤消/重做他们的编辑,即使例如用户接到电话并且活动在后台放置时也会被终止。我能想到的最佳解决方案是使用后台线程在应用程序使用期间不断地将我的命令和备忘录对象保存到磁盘,并在调用 onPause 时完成保存留在后台线程中的任何对象。在更糟糕的情况下,如果线程被杀死,我只会丢失一些编辑。

采纳答案by CommonsWare

In what situations will the OS kill the thread and how commonly do these situations occur?

在什么情况下操作系统会终止线程,这些情况发生的频率如何?

The OS will not kill the thread, unless it is killing the process -- Android does not do anything with threads you create yourself. If you are the foreground process, you will not be killed. The odds of Android killing the process within a few seconds of you losing the foreground (after onPause()) are miniscule. The documentation on process lifetime -- what there is of it -- can be found here.

操作系统不会终止线程,除非它终止进程——Android 不会对您自己创建的线程执行任何操作。如果你是前台进程,你不会被杀死。Android 在您失去前景(之后onPause())的几秒钟内终止进程的几率微乎其微。可以在此处找到有关进程生命周期的文档(其中包含哪些内容)。

回答by beekeeper

Your thread may be killed at any time after the activity is destroyed, or it may never be killed. Depending upon such a thread is very bad form -- you could end up with a half-completed operation, or with a thread that sticks around forever.

您的线程可能会在活动被销毁后随时被杀死,也可能永远不会被杀死。依赖于这样的线程是非常糟糕的形式——你可能会以一个半完成的操作结束,或者一个永远存在的线程。

If you wish to perform a background operation that continues even when there is no foreground activity, you almost always want to run it inside a Service. On the other hand, the service is less likelyto be killed, but there's no guarantee unless you use "startForeground". This will end up displaying a notification to the user that something is happening in the background, but as far as I know it's the only way of running an asynchronous background thread that is guaranteed not to be killed.

如果您希望在没有前台活动时继续执行后台操作,您几乎总是希望在服务中运行它。另一方面,服务被杀死的可能性较小,但除非您使用“startForeground”,否则无法保证。这最终会向用户显示一个通知,告诉用户后台正在发生某些事情,但据我所知,这是运行保证不会被杀死的异步后台线程的唯一方法。

Honestly, the right answer is to make sure that there is never any temporary process state that will take a long time to save. If you are having to write a large file to reflect a few user changes, consider maintaining a "transaction log" which you can use to create a restartable save operation. Given this, you can safely run your saves in a service and know that even if it gets killed, it will be automatically restarted when resources become available.

老实说,正确的答案是确保永远不会有任何需要很长时间才能保存的临时进程状态。如果您必须编写一个大文件来反映一些用户更改,请考虑维护一个“事务日志”,您可以使用它来创建可重新启动的保存操作。鉴于此,您可以安全地在服务中运行您的保存,并且知道即使它被杀死,当资源可用时它也会自动重新启动。

回答by EboMike

Normally, saving your state in onPauseis the right thing to do if it's quick. I don't think it's clearly documented when a process is killed, but you sometimes see it in logcat when you run some demanding apps (say, after running Google Earth and Browser).

通常,onPause如果速度快,则将状态保存在其中是正确的做法。我认为在进程被终止时没有明确记录,但是当您运行一些要求苛刻的应用程序时(例如,在运行 Google 地球和浏览器之后),您有时会在 logcat 中看到它。

There's also an option in the Android DevTools to automatically destroy activities as you navigate away from them, although that probably doesn't extend to the process. (DevTools are on the emulator, and on some rooted phones).

Android DevTools 中还有一个选项可以在您离开活动时自动销毁活动,尽管这可能不会扩展到流程。(DevTools 在模拟器上,在一些有 root 权限的手机上)。

I think your approach sound reasonable - use a low-priority thread to constantly update the save data, and give it normal priority in onPause, and set a flag in onPause that tells it to terminate after it finishes.

我认为您的方法听起来很合理 - 使用低优先级线程不断更新保存数据,并在 onPause 中为其赋予正常优先级,并在 onPause 中设置一个标志,告诉它在完成后终止。

Obviously, you'll need to make sure you don't run into synchronization issues if you get to onResume immediately after onPause (i.e. while the thread is still busy saving).

显然,如果在 onPause 之后立即进入 onResume(即当线程仍在忙于保存时),则需要确保不会遇到同步问题。