例如,有很多任务发布到 UI 线程,如下所示。
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
// Some logic to display/update something in UI
}
}, 5000);
当安卓应用程序进入后台时,这些任务会发生什么?
即使在后台也会处理这些任务吗?整个 UI 线程是否会在后台挂起?或?发布到 UI 线程的所有任务都已挂起?
如果活动完全加载后没有发布任何任务,UI 线程会发生什么情况?如果 Looper 中没有任务,它会被暂停吗?
提前谢谢。
让我们先用几个术语弄脏。
处理器:
处理程序允许从其他线程与 UI 线程通信 后台线程。这在安卓中很有用,因为安卓不允许 其他线程直接与 UI 线程通信。 用技术术语来说,这是一种发布消息或运行到关联线程消息队列的方法。
所以总共有两个任务由处理程序执行
- 将消息和可运行对象安排为将来某个时间点执行;以及
- 将要在与您自己的线程不同的线程上执行的操作排队。
那么如何安排一个
post(Runnable),
postAtTime(Runnable, long),
postDelayed(Runnable, Object, long),
sendEmptyMessage(int),
sendMessage(Message),
sendMessageAtTime(Message, long),
sendMessageDelayed(Message, long).
卢珀:
无论我之前提到的是什么,都由 Looper 支持,它有一个
loop()
方法,它继续运行并侦听新消息,主线程有一个一直在运行,因此您可以从另一个线程接收消息到该线程,如果您正在创建自己的线程并想要侦听,那么不要忘记在线程中调用 prepare() 运行循环。
一个简单的例子
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
所以现在回答你的问题:
1:事物(线程等 Looper 和处理程序)继续运行,直到它被用户完成或被系统杀死。
2:looper 有一个 loop() 方法,该方法将处理队列中的每个消息,并在队列为空时阻塞。
3:如果从后台线程更新 UI,请确保应用程序位于前台或在 onDestroy() 中终止后台线程,您可以使用handler.getLooper().quitSafely()
退出 looper 处理消息,或者如果处理程序附加到主线程,则可以使用handler.looper.quit()
退出 looper 处理消息。
建议在方向更改或其他配置更改的情况下确保终止后台线程。
关于这个案子有很多答案。我将尝试准确回答这些问题。
当安卓应用程序进入后台时,这些任务会发生什么?
没有任何东西被打断。Handler
将在指定时间发布Message
MessageQueue
(除非托管进程被终止)。
这些任务即使在后台也会处理吗?
从Handler
的角度来看:它不知道应用程序是在前台还是后台。它所知道的是,它应该在一段时间后发布Message
。
整个 UI 线程是否会在后台挂起?或?发布到 UI 线程的所有任务都已挂起?
如果活动完全加载后没有发布任何任务,UI 线程会发生什么情况?如果 Looper 中没有任务,它会被暂停吗?
在任何情况下,UI 线程都不会"挂起">(除非托管进程被终止)。只是由于MessageQueue
是空的,它会闲置——因此不需要做任何工作。
作为旁注,当应用进入后台时,请不要执行与 UI 相关的操作,因为视图层次结构的状态将无法正确保存。假设当应用程序处于后台时,您一次执行了textView.setText("bob")
。现在,不会保存此TextView
的状态,因为onSaveInstanceState()
已经执行并且不会再次执行,因此,如果应用程序的进程被终止并重新创建(即由于系统资源不足),则活动将以调用onSaveInstanceState()
时的状态恢复。现在用户不会看到"鲍勃"。
您可以使用 API 取消计划Handler#removeCallbacks()
事件。
UI 线程也称为主线程,它是打开应用程序时默认启动的线程,除非您将它们卸载到其他线程,否则所有交互都会发生。它不依赖于应用的可见性,只要应用存在,它就会运行。它不会被系统挂起。
如果活动完全加载后没有发布任何任务,UI 线程会发生什么情况?如果 Looper 中没有任务,它会被暂停吗?
让我们从 Looper 概念开始。这对于了解 UI 线程的工作方式非常重要。Looper 是一种在给定线程中循环并处理传入消息的东西,当没有任务时,它会循环并等待新任务,因此,回答您的最后一个问题,线程不会被挂起。Looper 旨在即使在没有任务的情况下也能保持线程的活动状态。默认情况下,Android 中的 UI 线程有自己的 Looper。
当安卓应用程序进入后台时,这些任务会发生什么? 这些任务即使在后台也会处理吗?整个 UI 线程是否会在后台挂起?或?发布到 UI 线程的所有任务都已挂起?
进入后台不会更改主线程的任何内容。它一直运行,直到应用程序被终止。因此,在处理程序上计划的代码将只运行。
附带说明一下。这里可能的问题是,当活动在后台时,它可能会被系统杀死,并且您尝试更改它的 UI 会使应用程序崩溃(有一些类似的情况),但它与 UI 线程并不真正相关。
总而言之,UI 线程在任何情况下都不会被框架挂起。它只是运行并处理您提供给它的所有内容,或者等到赋予它新任务。
在这里,您可以在官方文档中找到主线程的描述。
这是一个很好的关于活套的SO线程。
当安卓应用程序转到 背景?
它将按预期工作,UI 更改的行为没有变化。唯一的问题是我们无法看到这些变化。
最佳解决方案:当应用处于后台时更新处理程序中的任何视图
例如:TextView 并在其中设置一些文本,并在应用程序进入前台后获取此TextView值。
这些任务即使在后台也会处理吗?将 完整的 UI 线程在后台挂起?或?所有任务 发布到 UI 线程被暂停?
正如我上面提到的,此任务将按原样工作。
当您移动到后台时,应用程序不会更改 UI 线程,它将保持原样。
之后没有发布任何任务时,UI 线程会发生什么情况 活动已完全加载?如果有的话,是否会暂停 没有任务在 Looper 中?
简单地说,有 Looper 线程,例如 UI 线程。这样的线程有自己的 Looper,它为线程运行消息循环。消息队列完成后,它本身将完成。
UI 线程不会自行挂起,直到并且除非您编写一些代码来:)更改它。
很高兴阅读:Androids Handler.post,到底发生了什么
Android 中的 Looper、Handler 和 MessageQueue 之间有什么关系?