×

Android系统源码分析-Broadcast注册和注销

96
翰墨飘香
2017.12.26 13:50* 字数 1632

距离上一篇博客进程的加载过了很久的时间,这中间换了一份工作,加入了新的团队,也开始了新的项目,比较忙,所以最近才有时间将四大组件之一的广播原理看完,最近一段时间会相继把四大组件分析写完,让我们对四大组件有更深的了解。本来想一篇把广播的内容写完,但是发现要解释的代码比较多,所以还是分开来讲,那么这篇先分析广播的注册和注销,下一篇再分析广播的发送。

Broadcast的注册

注册广播时序图

Step-1:注册广播入口ContextImpl.registerReceiver:

    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return registerReceiver(receiver, filter, null, null);
    }

然后调用registerReceiver复写方法:

@Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                                   String broadcastPermission, Handler scheduler) {
        return registerReceiverInternal(receiver, getUserId(),
                filter, broadcastPermission, scheduler, getOuterContext());
    }

Step-2:调用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是描述当前应用程序进程的
                    scheduler = mMainThread.getHandler();
                }
                // 将广播接收者receiver封装成一个实现了IIntentReceiver接口的Binder对象rd(ReceiverDispatcher)
                rd = mPackageInfo.getReceiverDispatcher(
                        receiver, context, scheduler,
                        mMainThread.getInstrumentation(), true);
            } else {
                if (scheduler == null) {
                    // 获取主线程的Handler
                    scheduler = mMainThread.getHandler();
                }
                // 将广播接收者receiver封装成一个实现了IIntentReceiver接口的Binder对象rd(ReceiverDispatcher)
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {
            // 调用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类型对象,这个对象是在一个应用启动的时候创建的。

Step-3:LoadedApk.getReceiverDispatcher方法:

    // 每一个注册过广播接收者的Activity组件在LaodApk类中都有一个对应的ReceiverDispatcher对象,它负责
    // 将这个被注册的广播接收者与注册它的Activity组件关联在一起。这些ReceiverDispatcher对象保存在一个
    // HashMap中,并且以它们所关联的广播接收者为关键字。最后用来保存这些ReceiverDispatcher对象的HashMap
    // 又以它们所关联的Activity组件的Context接口为关键字保存在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) {
                // 查找有没有对应的广播接收者对象列表
                map = mReceivers.get(context);
                if (map != null) {
                    // 查找是否存在该广播接收者对应的ReceiverDispatcher对象
                    rd = map.get(r);
                }
            }
            if (rd == null) {// 不存在
                // 初始化广播接收器调度员
                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 {
                // 验证广播分发者的Context和Handler是否一致。
                rd.validate(context, handler);
            }
            rd.mForgotten = false;
            return rd.getIIntentReceiver();
        }
    }

这里主要是将广播接收者receiver封装成一个实现了IIntentReceiver接口的Binder对象rd,然后将其放置到LoadedApk对象中的mReceivers中保存起来。

再回到上面代码中,将生成的实现了IIntentReceiver接口的Binder对象rd通过mRemote.transact方法传递到ActivityManagerService中的registerReceiver方法,因为四大组件的消息传递都是通过这种方式实现的。

Step-7:ActivityManagerProxy.registerReceiver

 public Intent registerReceiver(IApplicationThread caller, String packageName,
                                   IIntentReceiver receiver,
                                   IntentFilter filter, String perm, int userId) throws RemoteException {
        ...
        // 通过内部的一个Binder代理对象mRemote向AMS发送一个类型为REGISTER_RECEIVER_TRANSACTION的进程
        // 间通信请求
        mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
        ...
        return intent;
    }

Step-8:ActivityManagerService.registerReceiver

通过上面的mRemote.transact方法传递到ActivityManagerService中对应的方法:

/**
 * 粘性广播(Sticky):一个粘性广播被发送到AMS后,就会一直保存在AMS中,直到AMS下次再接收到另外一个
 * 同类型的粘性广播为止。一个Activity组件在向AMS注册接收某一种烈性的广播时,如果AMS内部切好保存这个
 * 这种类型的粘性广播,那么AMS就会将这个粘性广播返回给Activity组件,以便它可以知道系统上一次发出的它
 * 所感兴趣的广播内容。我们可以通过sendStrickyBroadcast向AMS发送粘性广播
 */
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) {
                // 根据caller从ProcessRecord缓存列表中查询ProcessRecord对象caller,用来描述正在请求
                // AMS注册广播接收者的一个Activity组件所运行在的应用程序进程
                callerApp = getRecordForAppLocked(caller);
                if (callerApp == null) {// 没有对应进程,不能注册广播
                    ...//抛出异常
                }
                ...
            } else {
                ...
            }

            // 获取注册广播的用户的userId(UserController是多用户功能的用户管理,一些系统包含访客模式,或者多用户,每个用户就会有一个id)
            userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                    ALLOW_FULL_ONLY, "registerReceiver", callerPackage);

            // 获取需要注册广播的IntentFilter中所有的action
            Iterator<String> actions = filter.actionsIterator();
            // 如果注册广播没有Action则添加一个null
            if (actions == null) {
                ArrayList<String> noAction = new ArrayList<String>(1);
                noAction.add(null);
                actions = noAction.iterator();
            }

            // Activity组件在注册一个广播接收者时,并不是直接将这个广播接收者注册到了AMS中,而是将与它关联
            // 的一个InnerReceiver对象注册到了AMS中。当AMS接收到一个广播时,它就会根据这个广播的类型在内
            // 部知道对应的InnerReceiver对象,然后再通过这个对象将这个广播发送给对应的广播接收者。AMS中每
            // 一个广播接收者都是使用一个BroadcastFilter对象来描述的,而每一个BroadcastFilter对象又是根
            // 据它所描述的广播接收者所关联的一个BroadcastFilter对象,以及所要接受的广播类型来创建。由于在
            // 一个应用程序中,不同的Activity组件可能会使用同一个BroadcastFilter对象来注册不同的广播接收
            // 者,因此AMS会使用一个ReceiverList列表来保存这些使用了相同InnerReceiver对象来注册的广播接
            // 收者,并且以它们所使用的InnerReceiver对象为关键字。

            // Collect stickies of users
            // 收集与注册用户userId相关的所有已经被广播过的Intent,存储在stickyIntents中
            // 包含所有用户以及注册广播进程对应的用户
            // 第一个UserHandle.USER_ALL表示设备上所有的用户,
            // 第二个是callingUid对应用户的userId(当前用户的userId)
            int[] userIds = {UserHandle.USER_ALL, UserHandle.getUserId(callingUid)};
            // 这里只通过action进行过滤
            while (actions.hasNext()) {
                String action = actions.next();
                // 遍历与调度进程相关的用户id
                for (int id : userIds) {
                    // 根据userId查询已经发送过的对应的Intent列表
                    ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                    // 如果已经发送的Intent里包含上面要注册的广播的action的Intent,将其保存到stickyIntents中
                    if (stickies != null) {
                        // 根据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,则直接返回第一个Intent结束注册
            return sticky;
        }

        synchronized (this) {
            // 首先判断当前进程是否还活着
            if (callerApp != null && (callerApp.thread == null
                    || callerApp.thread.asBinder() != caller.asBinder())) {
                // Original caller already died(注册失败)
                return null;
            }
            // 首先从缓存中查找注册的receiver对应的ReceiverList(ArrayList<BroadcastFilter>),
            // 第一次注册为null,receiver对应的是一个BroadcastFilter列表,也就是说可以通过调用
            // registerReceiver来为receiver注册不同的广播条件。
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            // 缓存中没有,说明还没有注册过,如果有说明已经注册过了,不需要再添加
            if (rl == null) {
                // 如果没有就创建新的广播接收者(里面包含广播过滤器列表)列表
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    rl.app.receivers.add(rl);
                } else {
                    ...
                }
                // 这里面最关键的就是下面将receiver以及对应的ReceiverList列表放到mRegisteredReceivers中
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            } 
            ...
            // 创建BroadcastFilter对象bf,用来描述正在注册的广播接收者,并添加到ReceiverList队列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.
            // 上面注册结束以后,如果筛选出了与当前注册的IntentFilter匹配的sticky广播的Intent列表,
            // 就将所有匹配的Intent逐条发送广播给当前的注册者receiver,可以看到这里的接受者receivers
            // 里面就只有当前创建的一个BroadcastFilter,也就是当前的注册者。
            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);
                    // 根据Intent返回时前台广播队列还是后台广播队列
                    BroadcastQueue queue = broadcastQueueForIntent(intent);
                    // 需要发送的一条广播记录,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);
                    // 将该广播记录加入广播队列中
                    queue.enqueueParallelBroadcastLocked(r);
                    // 调度广播,发送BROADCAST_INTENT_MSG消息,触发处理下一个广播。但是如果目前有广播还在
                    // 发送的处理过程中,这次推动不会起作用
                    queue.scheduleBroadcastsLocked();
                }
            }

            return sticky;
        }
    }

上面时注册广播的核心代码,主要是先判断注册的广播的Action是不是已经存在AMS(ActivityManagerService)中的粘性广播中,如果存在就将这些Intent单独保存到一个列表中,然后处理广播接收器,上面代码和注释写的很清楚了,广播注册不是直接将receiver保存在AMS中,而是先将其封装到实现IIntentReceiver接口的Binder对象rd中,然后将这个对象放到ReceiverList对象中,这个ReceiverList对象是一个对应receiver的IntentFilter列表,但是这个列表对象也包含了该receiver对象,也就是将receiver以及其对应的IntentFilter列表封装到了ReceiverList对象中,这样每个广播接收者以及其Action都封装好了,然后将其放到该应用所在进程的ReceiverList对象列表中,这样整个广播注册就完成了。

其实缕清了这个结构就看懂广播注册了:首先是一个进程对象ProcessRecord,里面有一个广播的列表ArraySet<ReceiverList>,这个列表表示改进程注册的所有广播接收者,每个ReceiverList对象包含了一个广播接收者(实现了IIntentReceiver接口的Binder对象)封装和与该广播接收者对应的多个Action对应的IntentFilter对象的封装BroadcastFilter列表,这个ReceiverList对象是将注册的广播接收者以及对应的多个Action对应起来,这样就能查找对应的广播接收者,怎么调用我们下一篇发送广播会详细讲解。

Step-9:getRecordForAppLocked

final ProcessRecord getRecordForAppLocked(
            IApplicationThread thread) {
        if (thread == null) {
            return null;
        }

        int appIndex = getLRURecordIndexForAppLocked(thread);
        return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
    }

这里是根据IApplicationThread获取是否存在了该进程,这里调用getLRURecordIndexForAppLocked获取该进程对应的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循环来从mLruProcesses列表中遍历是否存在该IApplicationThread,如果存在返回对应的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等参数对应的用户id。

Step-24:BroadcastQueue.scheduleBroadcastsLocked

    // 驱动广播,所有广播都应该从这里走,然后会到processNextBroadcast
    public void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                + mQueueName + "]: current="
                + mBroadcastsScheduled);

        // mBroadcastsScheduled用来描述AMS是否已经向它所运行在的线程的消息队列发送了一个类型为
        // BROADCAST_INTENT_MSG的消息。AMS就是通过这个BROADCAST_INTENT_MSG消息类调度保存在无
        // 序广播调度队列mParallelBroadcasts和有序广播调度队列mOrderedBroadcasts中的广播转发任务的
        if (mBroadcastsScheduled) {// 如果true说明消息队列已经存在一个类型为BROADCAST_INTENT_MSG的消息了
            return;
        }
        // 虽然这里只发送了发送广播的消息,但是这一步执行完之后就已经标记广播发送了,因此可以看出广播发送和接
        // 受是异步的,即广播发送者将一个广播发送给AMS后,不会等待AMS将这个广播转发给广播接收者处理
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

Broadcast的注销

了解了广播注册,广播注销就很简单了,就是从列表中删除对应的广播对象封装。

注销广播时序图

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方法获取与该注销广播接收者对应的实现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中获取,我们从上面注册知道,注册时会将实现了IIntentReceiver接口的广播接收者的封装放到mReceivers保存,所以这里先去获取有没有,注册了肯定是有的,因此将其移除。

Step-4:ActivityManagerProxy.unregisterReceiver

    public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException {
        ...
        mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0);
        ...
    }

上面注册广播我们分析过调用ActivityManagerProxy这里的方法,然后通过Binder传递到AMS中对应的方法中

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) {
                        // 从广播接收器对应的进程中移除
                        rl.app.receivers.remove(rl);
                    }

                    // 移除对应广播过滤器
                    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);
        }
    }

找到对应的注册广播对象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;
    }

从队列中找到对应的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;
    }

这里判断是否结束广播接收,如果结束则处理下一条广播。

Step-10:BroadcastQueue.processNextBroadcast

这个是处理下一条广播的,也是广播的核心部分,这个我们在下一篇发送广播时会详细讲解。

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));
        }
    }

这个就是通过for循环删除对应的BroadcastFilter对象,这样就注销了广播。

主要的基本都分析了,还有以下其他不重要的大家想要了解自己看看代码。

广播注册结构

注册广播结构图

最后这里我们再加一个广播注册结构的总结,上面是一个广播注册时的结构图,也就是广播以及对应的IntentFilter列表封装,整个过程是由下向上注册。首先是将BroadcastReceiver封装成Binder对象IIntentReceiver,将IntentFilter封装成BroadcastFilter对象,ReceiverList继承的是ArrayList<BroadcastFilter>,因此它本身就是一个用来盛放BroadcastFilter对象列表的ArrayList对象,同时ReceiverList对象还放入了IntentFilter列表对应的BroadcastReceiver的封装对象IIntentReceiver,这样就将BroadcastReceiver和IntentFilter绑定到一起了,然后将ReceiverList放到mRegisteredReceivers中,保存在ActivityManagerService(AMS)中,同时将ReceiverList放置到该广播所在进程的receivers中,而该进程保存在AMS中的mLruProcesses中,同时将IntentFilter的封装对象BroadcastReceiver放置到AMS中的mReceiverResolver中,这样就注册完成了。

这样从整个机构来说就非常清楚了,其实里面还有一些相互引用的情况,我没有完全画出来,只画了主要的部分,相对清晰一些。

首发地址:http://www.codemx.cn

Android开发群:192508518

微信公众账号:Code-MX


注:本文原创,转载请注明出处,多谢。

Android技术分析
Web note ad 1