BroadcastReceiver.onReceiveは常にUIスレッドで実行されますか?


117

私のアプリでは、カスタムを作成し、BroadcastReceiverを介して手動でコンテキストに登録しContext.registerReceiverます。また、AsyncTaskを介してnotifier-Intentsをディスパッチするも持っていContext.sendBroadcastます。インテントは非UIワーカースレッドから送信されますが、(上記のインテントBroadcastReceiver.onReceiveを受信する)は常にUIスレッドで実行されるようです(これは私にとっては良いことです)。これは保証されていますか、それとも信頼すべきではありませんか?

回答:


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 2011

31
@CommonsWare:「メインアプリケーション( "UI")スレッド以外のスレッドでonReceive()が呼び出されるケースは考えられない」-BroadcastReceiverがregisterReceiver(BroadcastReceiver、IntentFilter、String、ハンドラ)、ハンドラ引数はnullではなく、メインアプリケーションスレッド以外のスレッドで作成されたハンドラを参照します。
ジュール

76

レシーバーを動的に登録するので、(UIスレッド以外の)別のスレッドがを処理するように指定できますonReceive()。これは、registerReceiver()の Handlerパラメーターを介して行われます 。

つまり、別のハンドラーを指定しなかった場合は、常にUIスレッドで処理されます。


はい。Handlerパラメーターを使用して変更できるように聞こえるのは、ドキュメントで言語を「ヘッジ」した理由です。
Andrew Mackenzie 14年

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を回避することです。
gマレ

9

以前の答えが正しく述べられているので、onReceive登録されているスレッドで実行されるのは、 registerReceiver()られているように、ハンドラーを受け入れるが呼び出さます。そうでない場合は、メインスレッドで実行されます。

受信機が登録されている場合を除きLocalBroadcastManager、ブロードキャストである経由して sendBroadcastSync、それはどこでしょう- 明らかに呼び出しというスレッドで実行sendBroadcastSync.


私はその部分に同意しませんand the broadcast is via sendBroadcastSync。私たちが使用した場合LocalBroadcastManagerレシーバを登録するには、それはメインスレッドを使用するかどうかによって呼び出されなければなりませんsendBroadcastSyncsendBroadcast。したがって、重要なのは、LocalBroadcastManager登録に使用することです。私は正しいですか?
kidoher、2015

@kidoher:ここのコードリンクをたどりましたか:stackoverflow.com/q/20820244/281545
Mr_and_Mrs_D 2015

0

YES Context.registerReceiver(BroadcastReceiverレシーバー、IntentFilterフィルター、文字列broadcastPermission、ハンドラースケジューラー)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.