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리시버를 등록하기 위해서는 메인 쓰레드 여부를 사용하여 호출해야합니다 sendBroadcastSync나 sendBroadcast. 그래서 핵심은 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.