sendBroadcastSync()
is indeed run on the thread it is called from (except if there is a race going on). Its implementation should be:
public void sendBroadcastSync(Intent intent) { // directly calls executePendingBroadcasts
if (sendBroadcast(intent)) {
executePendingBroadcasts();
}
}
The race part I am not sure about enters via the sendBroadcast()
call which returns true if it found any matching receiver (registered with LBM for this intent), after sending a message to a private handler associated with the main loop - abbreviated:
@Override
public boolean sendBroadcast(Intent intent) {
synchronized (mReceivers) {
final String action = intent.getAction();
final ArrayList<ReceiverRecord> entries = mActions.get(action);
if (entries == null) return false; // no receivers for that action
ArrayList<ReceiverRecord> receivers = new ArrayList<ReceiverRecord>();
for (ReceiverRecord receiver : entries) {
if (receiver.broadcasting) continue;
// match the intent
int match = receiver.filter.match(action,
intent.resolveTypeIfNeeded(mAppContext.getContentResolver()),
intent.getScheme(), intent.getData(),
intent.getCategories(), "LocalBroadcastManager");
if (match >= 0) {
receivers.add(receiver);
receiver.broadcasting = true;
}
}
final int size = receivers.size();
if (size == 0) return false; // no receivers for this intent
for (int i = 0; i < size; i++) {
receivers.get(i).broadcasting = false;
}
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
}
where:
mHandler = new Handler(context.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EXEC_PENDING_BROADCASTS:
executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}
I am not sure if there can be a race between the main thread and the thread sendBroadcastSync()
is executing - so the executePendingBroadcasts()
will run on the main thread. If not then executePendingBroadcasts()
runs on the thread sendBroadcastSync
is run and directly calls the onReceive of the receivers
One of these days I should look into why (in executePendingBroadcasts) synchronized(mReceivers)
and not synchronized(mPendingBroadcasts)
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…