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

Han*_*ruß 112 android

在我的应用程序中,我创建一个自定义BroadcastReceiver并通过手动注册到我的上下文Context.registerReceiver.我也有一个AsyncTask发送通知程序 - Intents via Context.sendBroadcast.意图是从非UI工作线程发送的,但似乎BroadcastReceiver.onReceive(接收所述Intents)总是在UI线程中运行(这对我有好处).这是保证还是我不应该依赖它?

Com*_*are 155

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

是.

  • @CommonsWare:"我想不出在主应用程序("UI")线程以外的线程上调用onReceive()的任何情况" - 如果使用registerReceiver注册BroadcastReceiver(BroadcastReceiver,IntentFilter,String, Handler),handler参数不为null,并且指的是在主应用程序线程以外的线程中创建的处理程序. (30认同)
  • @hannes:99.44%的时间,如果Android正在调用你的代码,它就在主应用程序线程上.在主应用程序线程上调用所有生命周期方法(例如,`onCreate()`,`onReceive()`).并且,它在`onReceive()`的文档中有记录:http://goo.gl/8kPuH (14认同)
  • 这是在某处记录的吗? (9认同)
  • @HannesStruß:我不知道他们为什么用"正常"对冲他们的语言.我想不出在主应用程序("UI")线程以外的线程上调用`onReceive()`的任何情况. (4认同)
  • 好吧,我只是将"通常在主线程中调用"从文档中解释为"总是"并希望事情不会破坏;-)谢谢! (2认同)
  • @朱尔斯:啊,非常正确-我很抱歉。 (2认同)
  • @androiddeveloper:“是否可以使broadcastReceiver在后台线程上工作,但无需通过代码(即清单文件的含义)进行设置?” -不 “我注意到这是一个名为“ goAsync”的函数,但仅从API 11中可用。“-欢迎您使用它。我发现`goAsync()`的文档缺少一些细节,因此我更喜欢使用其他方式,例如将工作委托给服务。 (2认同)
  • 如果使用LocalBroadcastManager.getInstance(this).registerReceiver()和sendBroadcastSync(),则onReceive()在广播发送者的线程上运行。在我的应用程序中,这意味着它有时是主线程,有时是后台线程。 (2认同)

Tom*_*yTh 74

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

也就是说,如果你没有指定另一个Handler,它将始终在UI线程上处理.


Can*_*ner 61

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

通常,这完全取决于您如何注册.

如果您注册BroadcastReceiver使用:

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
Run Code Online (Sandbox Code Playgroud)

它将在主活动线程(也称为UI线程)中运行.

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

registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)
Run Code Online (Sandbox Code Playgroud)

它将在你的上下文中运行 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
Run Code Online (Sandbox Code Playgroud)

详情在这里这里.

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

Mr_*_*s_D 9

如前所述正确陈述的答案onReceive将在其注册的线程上运行,如果registerReceiver()它接受处理程序的味道 被调用 - 否则在主线程上.

除非接收者已注册LocalBroadcastManager并且广播是通过 sendBroadcastSync- 它显然会在调用的线程上运行sendBroadcastSync.