BroadcastReceiver.onReceive是否始终在UI线程中运行?


117

在我的应用中,我创建了一个自定义BroadcastReceiver,然后通过手动将其注册到我的上下文中Context.registerReceiver。我也有一个AsyncTask通过调度notifier-Intents的方法Context.sendBroadcast。这些意图是从非UI工作线程发送的,但似乎BroadcastReceiver.onReceive(接收到所述意图)总是在UI线程中运行(这对我有好处)。这是可以保证的还是我不应该依赖于此?

Answers:


163

BroadcastReceiver.onReceive是否始终在UI线程中运行?

是。


9
这记录在某处吗?
HannesStruß2011年

15
@hannes:99.44%的时间,如果Android正在调用您的代码,则它在主应用程序线程上。所有的生命周期方法(例如onCreate()onReceive())被称为主应用程序线程上。并且,它在以下文档的文档中进行了记录onReceive()goo.gl/8kPuH
CommonsWare

2
好的,我只是将文档中的“通常在主线程中调用”解释为“总是”,并希望事情不会中断;-)谢谢!
HannesStruß2011年

4
@HannesStruß:我不知道为什么他们用“通常”来对冲自己的语言。我想不出onReceive()在主应用程序(“ UI”)线程以外的线程上调用的任何情况。
CommonsWare

31
@CommonsWare:“我无法想到在除主应用程序(“ UI”)线程之外的其他线程上调用onReceive()的任何情况。处理程序),处理程序参数不为null,并引用在主应用程序线程以外的线程中创建的处理程序。
2013年

76

由于您是动态注册接收者,因此可以指定另一个线程(UI线程除外)来处理onReceive()。这是通过registerReceiver()的Handler参数完成的 。

也就是说,如果您未指定其他处理程序,它将始终在UI线程上进行处理。


是。听起来您可以通过Handler参数进行更改,这就是为什么他们在文档中“对冲”他们的语言的原因。
2014年

64

BroadcastReceiver.onReceive是否始终在UI线程中运行?

通常,这取决于您如何注册。

如果您注册BroadcastReceiver使用:

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

它将在主活动线程(又名UI线程)中运行

如果您在其他线程上BroadcastReceiver使用有效的Handler 运行进行注册:

registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)

它将在您的上下文中运行 Handler

例如:

HandlerThread handlerThread = new HandlerThread("ht");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
context.registerReceiver(receiver, filter, null, handler); // Will not run on main thread

这里这里的细节。


3
在看了一段时间之后,我最终意识到LocalBroadcastManager不支持使用自定义处理程序。因此,如果您使用LBM而不是上下文来注册接收者,则此方法不适用。不幸的是,在那种情况下,似乎剩下的唯一选择是使用服务进入后台,并避免接收器在不活动10秒钟后触发的ANR。
gMale

9

正如前面正确回答的答案一样onReceive,如果registerReceiver()调用了接受处理程序的代码,它将在注册的线程上运行 -否则在主线程上运行。

除非接收方已向进行注册,LocalBroadcastManager而广播是通过 sendBroadcastSync-进行的,则显然它将在调用的线程上运行sendBroadcastSync.


我不同意这一部分and the broadcast is via sendBroadcastSync。当我们使用LocalBroadcastManager注册接收者时,无论使用sendBroadcastSync还是,主线程都必须调用它sendBroadcast。所以关键是LocalBroadcastManager用来注册。我对吗?
kidoher 2015年

@kidoher:您是否遵循以下代码链接:stackoverflow.com/q/20820244/281545
Mr_and_Mrs_D 2015年

0

是Context.registerReceiver(BroadcastReceiver接收器,IntentFilter过滤器,字符串broadcastPermission,Handler调度程序)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.