四大组件之BroadcastReceiver,进程间通信的一种方式,简单来讲,注册erceiver时将filiter,和receiver最想保存到一个列表,当发送Intent的时候查找列表,找到receiver将信息发送到指定Receiver。具体看一下源码。
从registerReceiver()这个函数开始,和startService,bindService一样也是由ContextImpl这个类来实际执行。
1)注册
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
通过ReceiverDispatcher 建立起InnerReceiver和Receiver之间的关系。InnerReceiver是一个Binder,在InnerRecevier中有方法performReceive()这里可回调onReceive()先不去管它。
ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
使用ActivityManagerService将InnerReceiver和filter保存到列表中。
/**
* Keeps track of all IIntentReceivers that have been registered for broadcasts.
* Hash keys are the receiver IBinder, hash value is a ReceiverList.
*/
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
保存在这个map里面 InnerReceiver和filiter,注册过程就完成了,onReceive不再当前进程,要调用需要Binder转发。
2)接收
发送使用sendBroadcast()这个方法,还是ContextImpl这里实际执行。
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
使用ActivityManagerService来发送,在这里查询出所有Intent对应的InnerReceiver
broadcastIntentLocked()在这个方法中查询过程复杂而繁琐,
if (!replaced) {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
在最后查询的queue对象就有所有符合的Receiver,有序广播可能还要排个序。
BroadcastQueue .java
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
看一下Handler怎么处理
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
processNextBroadcast(true);
} break;
它调用了processNextBroadcast(),
deliverToRegisteredReceiverLocked()//找到targetReceiver代码中遍历所有的brocastReceiver,找到之前ReceiverDispatcher 里面的InnerReceiver,
performReceiveLocked()//调用InnerReceiver的performReceive()回过头看一下注册时候的InnerReceiver。
在InnerReceiver中通用ReceiverDispatcher 的performReceive()
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
mActivityThread.post(args)这句话,将在注册线程中执行此arg这个arg是个runnable。
在run方法中调用了onReceive()
receiver.onReceive(mContext, intent);
这样就完成了Receiver()接受的过程。