BroadcastReceiver.onReceive는 항상 UI 스레드에서 실행됩니까?


117

내 앱에서 사용자 지정을 만들고 BroadcastReceiver.NET을 통해 수동으로 내 Context에 등록합니다 Context.registerReceiver. 또한을 AsyncTask통해 notifier-Intents를 전달 하는 Context.sendBroadcast. 의도는 비 UI 작업자 스레드에서 전송되지만 BroadcastReceiver.onReceive(인 텐트를 수신하는) 항상 UI 스레드에서 실행되는 것 같습니다 (나에게 좋습니다). 이것이 보장됩니까, 아니면 그것에 의존하지 않아야합니까?

답변:


163

BroadcastReceiver.onReceive는 항상 UI 스레드에서 실행됩니까?

예.


9
어딘가에 문서화되어 있습니까?
Hannes Struß 2011

15
@hannes : 99.44 %의 경우 Android가 코드를 호출하는 경우 기본 애플리케이션 스레드에 있습니다. 모든 라이프 사이클 방법 (예를 들면 onCreate(), onReceive()) 주 응용 프로그램 스레드에서 호출된다. 그리고 다음 문서에 문서화되어 있습니다 onReceive(). goo.gl/8kPuH
CommonsWare

2
좋아, 나는 문서에서 "보통 메인 스레드 내에서 호출된다"를 "항상"으로 해석하고 일이 깨지지 않기를 바란다 ;-) 감사합니다!
Hannes Struß 2011

4
@Hannes Struß : 왜 그들이 그들의 언어를 "보통"으로 헷갈 리게했는지 모르겠습니다. onReceive()주 응용 프로그램 ( "UI") 스레드가 아닌 다른 스레드에서이 호출되는 경우 는 생각할 수 없습니다 .
CommonsWare 2011

31
@CommonsWare : "주 응용 프로그램 ("UI ") 스레드가 아닌 스레드에서 onReceive ()가 호출되는 경우를 생각할 수 없습니다."-BroadcastReceiver가 registerReceiver (BroadcastReceiver, IntentFilter, String, 핸들러), 핸들러 인수가 null이 아니며 메인 애플리케이션 스레드가 아닌 스레드에서 생성 된 핸들러를 참조합니다.
Jules

76

수신자를 동적으로 등록하기 때문에 다른 스레드 (UI 스레드 제외)가 onReceive(). 이는 registerReceiver () 의 Handler 매개 변수를 통해 수행됩니다 .

즉, 다른 Handler를 지정하지 않으면 항상 UI 스레드에서 처리됩니다.


예. Handler 매개 변수를 통해 변경할 수있는 능력이 문서에서 해당 언어를 "헤지"한 이유입니다.
Andrew Mackenzie

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리시버를 등록하기 위해서는 메인 쓰레드 여부를 사용하여 호출해야합니다 sendBroadcastSyncsendBroadcast. 그래서 핵심은 LocalBroadcastManager등록 을 사용 하는 것입니다. 내가 맞아?
kidoher

@kidoher : 여기에있는 코드 링크를 따랐습니까 ? stackoverflow.com/q/20820244/281545 ?
Mr_and_Mrs_D

0

YES Context.registerReceiver (BroadcastReceiver 수신기, IntentFilter 필터, String broadcastPermission, Handler 스케줄러)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.