Context의 sendBroadcast()
는 Binder IPC를 통해 ActivityManagerService를 거쳐야하므로 속도에서 이점이 크지 않다.
또한, Intent 액션을 안다면 원치 않는 곳에서도 이벤트를 받아서 예기치 않는 일을 할 가능성도 있다.
sendBroadcast()
에서는 파라미터로 전달되는 Intent에 setPackage()
메서드를 사용해서 원하는 패키지에만 브로드캐스트를 전달할 수 있다. 다만 이 방식은 ICS부터 동작한다.
프로세스 간에 브로드캐스트를 보낼 필요가 없다면 support-v4에 포함된 LocalBroadcastManager의 사용을 고려해보자.
로컬 프로세스에서만 이벤트를 주고받을 수가 있다. 시스템 브로드캐스트와는 구조가 완전히 다른데, ActivityManagerService를 거치지 않고 싱글톤인 LocalBroadcastManager에서 registerReceiver()
와 sendBroadcast()
를 실행한다.
LocalBroadcastManager.getInstance(this).sendBroadcast(CalendarIntent.CHANGE_TIME)
LocalBroadcastManager.getInstance(this).registerReceiver(...)
LocalBroadcastManager에 등록된 BroadcastReceiver의 sendBroadcast() 메서드는 BroadcastReceiver를 바로 실행하지 않는다.
Handler에 Message를 보내서 메인 스레드에서 가능한 시점에 처리한다. 따라서 메인 루퍼의 메세지큐에 쌓여 있는게 많다면 처리가 늦어질 수 있다.
그런데 인증 에러 같은 것을 메세지큐에서 처리하면 문제가 될 수 있다.
BroadcastReceiver에서 바로 처리해야하 하는데, 그렇지 않고 다른 작업을 먼저 한다면 타이밍상 엉뚱한 결과를 만들어 내는 경우가 생긴다. 이때 쓰는 것이 sendBroadcastSync() 메서드다!
등록된 브로드캐스트 리시버는 모두 그 순간에 처리하는데, 이 때 sendBroadcastSync()와 onReceive()는 동일한 스레드에서 실행된다.
LocalBroadcastManager에서 sendBroadcast()를 호출할 때 브로드캐스트 리시버의 한 종류인 앱 위젯에는 이벤트가 전달되지 않는다. 앱 위젯은 홈 스크린에서 설치되어 별도 프로세스에 있으므로, 글로벌 브로드캐스트를 사용해서 이벤트를 전달해야만 한다. 다만 앱 위젯의 onReceive() 실행 위치는 다시 앱의 프로세스이다.
안드로이드 프로그래밍 Next Step