距離上一篇博客進(jìn)程的加載過了很久的時(shí)間,這中間換了一份工作,加入了新的團(tuán)隊(duì),也開始了新的項(xiàng)目,比較忙,所以最近才有時(shí)間將四大組件之一的廣播原理看完,最近一段時(shí)間會(huì)相繼把四大組件分析寫完,讓我們對四大組件有更深的了解。本來想一篇把廣播的內(nèi)容寫完,但是發(fā)現(xiàn)要解釋的代碼比較多,所以還是分開來講,那么這篇先分析廣播的注冊和注銷,下一篇再分析廣播的發(fā)送。
Broadcast的注冊
Step-1:注冊廣播入口ContextImpl.registerReceiver:
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
然后調(diào)用registerReceiver復(fù)寫方法:
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext());
}
Step-2:調(diào)用registerReceiverInternal方法:
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
// 需要注冊的廣播接收器不為null
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
// 獲取主線程的Handler,mMainThread是描述當(dāng)前應(yīng)用程序進(jìn)程的
scheduler = mMainThread.getHandler();
}
// 將廣播接收者receiver封裝成一個(gè)實(shí)現(xiàn)了IIntentReceiver接口的Binder對象rd(ReceiverDispatcher)
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
// 獲取主線程的Handler
scheduler = mMainThread.getHandler();
}
// 將廣播接收者receiver封裝成一個(gè)實(shí)現(xiàn)了IIntentReceiver接口的Binder對象rd(ReceiverDispatcher)
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
// 調(diào)用ActivityManagerProxy的registerReceiver,最終通過mRemote.transact方法傳遞到
// ActivityManagerService中的registerReceiver方法
final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
...
return intent;
} catch (RemoteException e) {
...
}
}
mPackageInfo是LoadedApk類型對象,這個(gè)對象是在一個(gè)應(yīng)用啟動(dòng)的時(shí)候創(chuàng)建的。
Step-3:LoadedApk.getReceiverDispatcher方法:
// 每一個(gè)注冊過廣播接收者的Activity組件在LaodApk類中都有一個(gè)對應(yīng)的ReceiverDispatcher對象,它負(fù)責(zé)
// 將這個(gè)被注冊的廣播接收者與注冊它的Activity組件關(guān)聯(lián)在一起。這些ReceiverDispatcher對象保存在一個(gè)
// HashMap中,并且以它們所關(guān)聯(lián)的廣播接收者為關(guān)鍵字。最后用來保存這些ReceiverDispatcher對象的HashMap
// 又以它們所關(guān)聯(lián)的Activity組件的Context接口為關(guān)鍵字保存在LoadApk類的成員變量mReceivers中
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
// 是不是注冊廣播
if (registered) {
// 查找有沒有對應(yīng)的廣播接收者對象列表
map = mReceivers.get(context);
if (map != null) {
// 查找是否存在該廣播接收者對應(yīng)的ReceiverDispatcher對象
rd = map.get(r);
}
}
if (rd == null) {// 不存在
// 初始化廣播接收器調(diào)度員
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
// 緩存ReceiverDispatcher
map.put(r, rd);
}
} else {
// 驗(yàn)證廣播分發(fā)者的Context和Handler是否一致。
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
這里主要是將廣播接收者receiver封裝成一個(gè)實(shí)現(xiàn)了IIntentReceiver接口的Binder對象rd,然后將其放置到LoadedApk對象中的mReceivers中保存起來。
再回到上面代碼中,將生成的實(shí)現(xiàn)了IIntentReceiver接口的Binder對象rd通過mRemote.transact方法傳遞到ActivityManagerService中的registerReceiver方法,因?yàn)樗拇蠼M件的消息傳遞都是通過這種方式實(shí)現(xiàn)的。
Step-7:ActivityManagerProxy.registerReceiver
public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
IntentFilter filter, String perm, int userId) throws RemoteException {
...
// 通過內(nèi)部的一個(gè)Binder代理對象mRemote向AMS發(fā)送一個(gè)類型為REGISTER_RECEIVER_TRANSACTION的進(jìn)程
// 間通信請求
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
...
return intent;
}
Step-8:ActivityManagerService.registerReceiver
通過上面的mRemote.transact方法傳遞到ActivityManagerService中對應(yīng)的方法:
/**
* 粘性廣播(Sticky):一個(gè)粘性廣播被發(fā)送到AMS后,就會(huì)一直保存在AMS中,直到AMS下次再接收到另外一個(gè)
* 同類型的粘性廣播為止。一個(gè)Activity組件在向AMS注冊接收某一種烈性的廣播時(shí),如果AMS內(nèi)部切好保存這個(gè)
* 這種類型的粘性廣播,那么AMS就會(huì)將這個(gè)粘性廣播返回給Activity組件,以便它可以知道系統(tǒng)上一次發(fā)出的它
* 所感興趣的廣播內(nèi)容。我們可以通過sendStrickyBroadcast向AMS發(fā)送粘性廣播
*/
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
...
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
int callingUid;
int callingPid;
synchronized (this) {
if (caller != null) {
// 根據(jù)caller從ProcessRecord緩存列表中查詢ProcessRecord對象caller,用來描述正在請求
// AMS注冊廣播接收者的一個(gè)Activity組件所運(yùn)行在的應(yīng)用程序進(jìn)程
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {// 沒有對應(yīng)進(jìn)程,不能注冊廣播
...//拋出異常
}
...
} else {
...
}
// 獲取注冊廣播的用戶的userId(UserController是多用戶功能的用戶管理,一些系統(tǒng)包含訪客模式,或者多用戶,每個(gè)用戶就會(huì)有一個(gè)id)
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
// 獲取需要注冊廣播的IntentFilter中所有的action
Iterator<String> actions = filter.actionsIterator();
// 如果注冊廣播沒有Action則添加一個(gè)null
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
// Activity組件在注冊一個(gè)廣播接收者時(shí),并不是直接將這個(gè)廣播接收者注冊到了AMS中,而是將與它關(guān)聯(lián)
// 的一個(gè)InnerReceiver對象注冊到了AMS中。當(dāng)AMS接收到一個(gè)廣播時(shí),它就會(huì)根據(jù)這個(gè)廣播的類型在內(nèi)
// 部知道對應(yīng)的InnerReceiver對象,然后再通過這個(gè)對象將這個(gè)廣播發(fā)送給對應(yīng)的廣播接收者。AMS中每
// 一個(gè)廣播接收者都是使用一個(gè)BroadcastFilter對象來描述的,而每一個(gè)BroadcastFilter對象又是根
// 據(jù)它所描述的廣播接收者所關(guān)聯(lián)的一個(gè)BroadcastFilter對象,以及所要接受的廣播類型來創(chuàng)建。由于在
// 一個(gè)應(yīng)用程序中,不同的Activity組件可能會(huì)使用同一個(gè)BroadcastFilter對象來注冊不同的廣播接收
// 者,因此AMS會(huì)使用一個(gè)ReceiverList列表來保存這些使用了相同InnerReceiver對象來注冊的廣播接
// 收者,并且以它們所使用的InnerReceiver對象為關(guān)鍵字。
// Collect stickies of users
// 收集與注冊用戶userId相關(guān)的所有已經(jīng)被廣播過的Intent,存儲(chǔ)在stickyIntents中
// 包含所有用戶以及注冊廣播進(jìn)程對應(yīng)的用戶
// 第一個(gè)UserHandle.USER_ALL表示設(shè)備上所有的用戶,
// 第二個(gè)是callingUid對應(yīng)用戶的userId(當(dāng)前用戶的userId)
int[] userIds = {UserHandle.USER_ALL, UserHandle.getUserId(callingUid)};
// 這里只通過action進(jìn)行過濾
while (actions.hasNext()) {
String action = actions.next();
// 遍歷與調(diào)度進(jìn)程相關(guān)的用戶id
for (int id : userIds) {
// 根據(jù)userId查詢已經(jīng)發(fā)送過的對應(yīng)的Intent列表
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
// 如果已經(jīng)發(fā)送的Intent里包含上面要注冊的廣播的action的Intent,將其保存到stickyIntents中
if (stickies != null) {
// 根據(jù)action查詢Intent列表
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
stickyIntents.addAll(intents);
}
}
}
}
}
// 下面對通過action過濾出來粘性廣播的Intent列表,包括:action,type,scheme,data,categories
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// Look for any matching sticky broadcasts...
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// 查找與IntentFilter匹配的Intent
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
allSticky.add(intent);
}
}
}
...
if (receiver == null) {// 如果廣播接收器為null,則直接返回第一個(gè)Intent結(jié)束注冊
return sticky;
}
synchronized (this) {
// 首先判斷當(dāng)前進(jìn)程是否還活著
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died(注冊失敗)
return null;
}
// 首先從緩存中查找注冊的receiver對應(yīng)的ReceiverList(ArrayList<BroadcastFilter>),
// 第一次注冊為null,receiver對應(yīng)的是一個(gè)BroadcastFilter列表,也就是說可以通過調(diào)用
// registerReceiver來為receiver注冊不同的廣播條件。
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
// 緩存中沒有,說明還沒有注冊過,如果有說明已經(jīng)注冊過了,不需要再添加
if (rl == null) {
// 如果沒有就創(chuàng)建新的廣播接收者(里面包含廣播過濾器列表)列表
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
...
}
// 這里面最關(guān)鍵的就是下面將receiver以及對應(yīng)的ReceiverList列表放到mRegisteredReceivers中
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
...
// 創(chuàng)建BroadcastFilter對象bf,用來描述正在注冊的廣播接收者,并添加到ReceiverList隊(duì)列rl中
// 以及mReceiverResolver中
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
rl.add(bf);
...
// 添加到已注冊接收器的廣播解析器中,注冊完成
mReceiverResolver.addFilter(bf);
// Enqueue broadcasts for all existing stickies that match
// this filter.
// 上面注冊結(jié)束以后,如果篩選出了與當(dāng)前注冊的IntentFilter匹配的sticky廣播的Intent列表,
// 就將所有匹配的Intent逐條發(fā)送廣播給當(dāng)前的注冊者receiver,可以看到這里的接受者receivers
// 里面就只有當(dāng)前創(chuàng)建的一個(gè)BroadcastFilter,也就是當(dāng)前的注冊者。
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
// 根據(jù)Intent返回時(shí)前臺廣播隊(duì)列還是后臺廣播隊(duì)列
BroadcastQueue queue = broadcastQueueForIntent(intent);
// 需要發(fā)送的一條廣播記錄,receivers包含了所有能接收該條廣播的接收器
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1);
// 將該廣播記錄加入廣播隊(duì)列中
queue.enqueueParallelBroadcastLocked(r);
// 調(diào)度廣播,發(fā)送BROADCAST_INTENT_MSG消息,觸發(fā)處理下一個(gè)廣播。但是如果目前有廣播還在
// 發(fā)送的處理過程中,這次推動(dòng)不會(huì)起作用
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
上面時(shí)注冊廣播的核心代碼,主要是先判斷注冊的廣播的Action是不是已經(jīng)存在AMS(ActivityManagerService)中的粘性廣播中,如果存在就將這些Intent單獨(dú)保存到一個(gè)列表中,然后處理廣播接收器,上面代碼和注釋寫的很清楚了,廣播注冊不是直接將receiver保存在AMS中,而是先將其封裝到實(shí)現(xiàn)IIntentReceiver接口的Binder對象rd中,然后將這個(gè)對象放到ReceiverList對象中,這個(gè)ReceiverList對象是一個(gè)對應(yīng)receiver的IntentFilter列表,但是這個(gè)列表對象也包含了該receiver對象,也就是將receiver以及其對應(yīng)的IntentFilter列表封裝到了ReceiverList對象中,這樣每個(gè)廣播接收者以及其Action都封裝好了,然后將其放到該應(yīng)用所在進(jìn)程的ReceiverList對象列表中,這樣整個(gè)廣播注冊就完成了。
其實(shí)縷清了這個(gè)結(jié)構(gòu)就看懂廣播注冊了:首先是一個(gè)進(jìn)程對象ProcessRecord,里面有一個(gè)廣播的列表ArraySet<ReceiverList>,這個(gè)列表表示改進(jìn)程注冊的所有廣播接收者,每個(gè)ReceiverList對象包含了一個(gè)廣播接收者(實(shí)現(xiàn)了IIntentReceiver接口的Binder對象)封裝和與該廣播接收者對應(yīng)的多個(gè)Action對應(yīng)的IntentFilter對象的封裝BroadcastFilter列表,這個(gè)ReceiverList對象是將注冊的廣播接收者以及對應(yīng)的多個(gè)Action對應(yīng)起來,這樣就能查找對應(yīng)的廣播接收者,怎么調(diào)用我們下一篇發(fā)送廣播會(huì)詳細(xì)講解。
Step-9:getRecordForAppLocked
final ProcessRecord getRecordForAppLocked(
IApplicationThread thread) {
if (thread == null) {
return null;
}
int appIndex = getLRURecordIndexForAppLocked(thread);
return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
}
這里是根據(jù)IApplicationThread獲取是否存在了該進(jìn)程,這里調(diào)用getLRURecordIndexForAppLocked獲取該進(jìn)程對應(yīng)的index
Step-10:getLRURecordIndexForAppLocked
private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
IBinder threadBinder = thread.asBinder();
// Find the application record.
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord rec = mLruProcesses.get(i);
if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
return i;
}
}
return -1;
}
這里主要通過for循環(huán)來從mLruProcesses列表中遍歷是否存在該IApplicationThread,如果存在返回對應(yīng)的Index,否則返回-1.
Step-11:UserController.handleIncomingUser
int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
int allowMode, String name, String callerPackage) {
final int callingUserId = UserHandle.getUserId(callingUid);
if (callingUserId == userId) {
return userId;
}
...
int targetUserId = unsafeConvertIncomingUserLocked(userId);
if (callingUid != 0 && callingUid != SYSTEM_UID) {
final boolean allow;
if (mService.checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
// If the caller has this permission, they always pass go. And collect $200.
allow = true;
}
...
if (!allow) {
if (userId == UserHandle.USER_CURRENT_OR_SELF) {
// In this case, they would like to just execute as their
// owner user instead of failing.
targetUserId = callingUserId;
} else {
...
}
}
}
...
return targetUserId;
}
這里主要獲取callingPid等參數(shù)對應(yīng)的用戶id。
Step-24:BroadcastQueue.scheduleBroadcastsLocked
// 驅(qū)動(dòng)廣播,所有廣播都應(yīng)該從這里走,然后會(huì)到processNextBroadcast
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
// mBroadcastsScheduled用來描述AMS是否已經(jīng)向它所運(yùn)行在的線程的消息隊(duì)列發(fā)送了一個(gè)類型為
// BROADCAST_INTENT_MSG的消息。AMS就是通過這個(gè)BROADCAST_INTENT_MSG消息類調(diào)度保存在無
// 序廣播調(diào)度隊(duì)列mParallelBroadcasts和有序廣播調(diào)度隊(duì)列mOrderedBroadcasts中的廣播轉(zhuǎn)發(fā)任務(wù)的
if (mBroadcastsScheduled) {// 如果true說明消息隊(duì)列已經(jīng)存在一個(gè)類型為BROADCAST_INTENT_MSG的消息了
return;
}
// 雖然這里只發(fā)送了發(fā)送廣播的消息,但是這一步執(zhí)行完之后就已經(jīng)標(biāo)記廣播發(fā)送了,因此可以看出廣播發(fā)送和接
// 受是異步的,即廣播發(fā)送者將一個(gè)廣播發(fā)送給AMS后,不會(huì)等待AMS將這個(gè)廣播轉(zhuǎn)發(fā)給廣播接收者處理
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
Broadcast的注銷
了解了廣播注冊,廣播注銷就很簡單了,就是從列表中刪除對應(yīng)的廣播對象封裝。
Step-1:unregisterReceiver
public void unregisterReceiver(BroadcastReceiver receiver) {
if (mPackageInfo != null) {
IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
ActivityManagerNative.getDefault().unregisterReceiver(rd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
...
}
}
首先通過LoadedApk.forgetReceiverDispatcher方法獲取與該注銷廣播接收者對應(yīng)的實(shí)現(xiàn)IIntentReceiver接口的Binder對象。
Step-2:LoadedApk.forgetReceiverDispatcher
public IIntentReceiver forgetReceiverDispatcher(Context context,
BroadcastReceiver r) {
synchronized (mReceivers) {
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
LoadedApk.ReceiverDispatcher rd = null;
if (map != null) {
rd = map.get(r);
if (rd != null) {
map.remove(r);
if (map.size() == 0) {
mReceivers.remove(context);
}
...
return rd.getIIntentReceiver();
}
}
...
}
}
首先去mReceivers中獲取,我們從上面注冊知道,注冊時(shí)會(huì)將實(shí)現(xiàn)了IIntentReceiver接口的廣播接收者的封裝放到mReceivers保存,所以這里先去獲取有沒有,注冊了肯定是有的,因此將其移除。
Step-4:ActivityManagerProxy.unregisterReceiver
public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException {
...
mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0);
...
}
上面注冊廣播我們分析過調(diào)用ActivityManagerProxy這里的方法,然后通過Binder傳遞到AMS中對應(yīng)的方法中
Step-5:ActivityManagerService.unregisterReceiver
// 注銷廣播
public void unregisterReceiver(IIntentReceiver receiver) {
...
try {
boolean doTrim = false;
synchronized (this) {
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
// 如果不為null,說明還沒注銷廣播
if (rl != null) {
final BroadcastRecord r = rl.curBroadcast;
if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) {
final boolean doNext = r.queue.finishReceiverLocked(
r, r.resultCode, r.resultData, r.resultExtras,
r.resultAbort, false);
if (doNext) {
doTrim = true;
r.queue.processNextBroadcast(false);
}
}
if (rl.app != null) {
// 從廣播接收器對應(yīng)的進(jìn)程中移除
rl.app.receivers.remove(rl);
}
// 移除對應(yīng)廣播過濾器
removeReceiverLocked(rl);
if (rl.linkedToDeath) {
rl.linkedToDeath = false;
rl.receiver.asBinder().unlinkToDeath(rl, 0);
}
}
}
// If we actually concluded any broadcasts, we might now be able
// to trim the recipients' apps from our working set
if (doTrim) {
trimApplications();
return;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
找到對應(yīng)的注冊廣播對象ReceiverList,然后將其移除。
Step-6:BroadcastQueue.getMatchingOrderedReceiver
public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
if (mOrderedBroadcasts.size() > 0) {
final BroadcastRecord r = mOrderedBroadcasts.get(0);
if (r != null && r.receiver == receiver) {
return r;
}
}
return null;
}
從隊(duì)列中找到對應(yīng)的BroadcastRecord對象然后返回。
Step-8:BroadcastQueue.finishReceiverLocked
public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
final int state = r.state;
final ActivityInfo receiver = r.curReceiver;
r.state = BroadcastRecord.IDLE;
...
if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices
&& r.queue.mOrderedBroadcasts.size() > 0
&& r.queue.mOrderedBroadcasts.get(0) == r) {
ActivityInfo nextReceiver;
if (r.nextReceiver < r.receivers.size()) {
Object obj = r.receivers.get(r.nextReceiver);
nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo) obj : null;
} else {
nextReceiver = null;
}
// Don't do this if the next receive is in the same process as the current one.
if (receiver == null || nextReceiver == null
|| receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
|| !receiver.processName.equals(nextReceiver.processName)) {
if (mService.mServices.hasBackgroundServices(r.userId)) {
r.state = BroadcastRecord.WAITING_SERVICES;
return false;
}
}
}
r.curComponent = null;
// We will process the next receiver right now if this is finishing
// an app receiver (which is always asynchronous) or after we have
// come back from calling a receiver.
return state == BroadcastRecord.APP_RECEIVE
|| state == BroadcastRecord.CALL_DONE_RECEIVE;
}
這里判斷是否結(jié)束廣播接收,如果結(jié)束則處理下一條廣播。
Step-10:BroadcastQueue.processNextBroadcast
這個(gè)是處理下一條廣播的,也是廣播的核心部分,這個(gè)我們在下一篇發(fā)送廣播時(shí)會(huì)詳細(xì)講解。
Step-11:removeReceiverLocked
void removeReceiverLocked(ReceiverList rl) {
mRegisteredReceivers.remove(rl.receiver.asBinder());
for (int i = rl.size() - 1; i >= 0; i--) {
mReceiverResolver.removeFilter(rl.get(i));
}
}
這個(gè)就是通過for循環(huán)刪除對應(yīng)的BroadcastFilter對象,這樣就注銷了廣播。
主要的基本都分析了,還有以下其他不重要的大家想要了解自己看看代碼。
廣播注冊結(jié)構(gòu)
最后這里我們再加一個(gè)廣播注冊結(jié)構(gòu)的總結(jié),上面是一個(gè)廣播注冊時(shí)的結(jié)構(gòu)圖,也就是廣播以及對應(yīng)的IntentFilter列表封裝,整個(gè)過程是由下向上注冊。首先是將BroadcastReceiver封裝成Binder對象IIntentReceiver,將IntentFilter封裝成BroadcastFilter對象,ReceiverList繼承的是ArrayList<BroadcastFilter>,因此它本身就是一個(gè)用來盛放BroadcastFilter對象列表的ArrayList對象,同時(shí)ReceiverList對象還放入了IntentFilter列表對應(yīng)的BroadcastReceiver的封裝對象IIntentReceiver,這樣就將BroadcastReceiver和IntentFilter綁定到一起了,然后將ReceiverList放到mRegisteredReceivers中,保存在ActivityManagerService(AMS)中,同時(shí)將ReceiverList放置到該廣播所在進(jìn)程的receivers中,而該進(jìn)程保存在AMS中的mLruProcesses中,同時(shí)將IntentFilter的封裝對象BroadcastReceiver放置到AMS中的mReceiverResolver中,這樣就注冊完成了。
這樣從整個(gè)機(jī)構(gòu)來說就非常清楚了,其實(shí)里面還有一些相互引用的情況,我沒有完全畫出來,只畫了主要的部分,相對清晰一些。
注
首發(fā)地址:http://www.codemx.cn
Android開發(fā)群:192508518
微信公眾賬號:Code-MX
注:本文原創(chuàng),轉(zhuǎn)載請注明出處,多謝。