android系列之BroadcastReceiver的工作过程

纵饮孤独 提交于 2019-12-19 09:38:05

一:广播的注册过程

广播的动态注册过程是从ContextWrapperregisterReceiver方法开始的.代码如下:

ContextWrapperregisterReceiver方法并没有做实际的工作,而是把注册过程交给了ContextImpl来完成

    public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
    }

下面是ContextImpl的registerRceciver方法:

registerRceciver调用了registerReceiverInternal方法。

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

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

registerReceiverInternal方法如下:

    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();
                }
                /**
                 * 系统首先从mPackageInfo获取IIntentReceiver对象。然后采用夸进程的方式向AMS发送
                 * 广播注册请求。之所以采用IIntentReceiver而不是直接采用BroadcastReceiver,这是
                 * 因为上述注册过程是一个进程间通信的过程。
                 */
                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 {
            /**
             * 此处调用AMS的registerReceiver。进入服务进程
             */
            return ActivityManagerNative.getDefault().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName,
                    rd, filter, broadcastPermission, userId);
        } catch (RemoteException e) {
            return null;
        }
    }

系统首先从mPackageInfo获取IIntentReceiver对象,然后在采用夸进程的方式向AMS发送广播的注册请求。之所以采用IIntentReceiver二不是直接采用BroadcastReceiver,这是因为上述注册过程是一个进程间通信的过程,而BroadcastReceiver作为Android的一个组件是不能直接跨进程传递的。所以需要通过IIntentReceiver中转一下。毫无疑问,IIntentReceiver必须是一个Binder接口。它的具体实现是LoadedApk.ReceiverDispatcher.InnerReceiver,ReceiverDispatcher内部同时保存了BroadcastReceiver和InnerReceiver,这样当接收到广播时,ReceiverDispatcher可以很方便的调用BroadcastReceiver的onReceiver方法

    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
                 */
                map = mReceivers.get(context);
                if (map != null) {
                    /**
                     * 根据BroadcastReceiver自定义广播获取ReceiverDispatcher
                     */
                    rd = map.get(r);
                }
            }
            /**
             * 当没有创建和自定义广播绑定的ReceiverDispatcher则新建ReceiverDispatcher
             */
            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);
                    }
                    /**
                     * 建立自定义BroadcastReceiver和ReceiverDispatcher的关系
                     */
                    map.put(r, rd);
                }
            } else {
                /**
                 * 如果已经绑定则检查context和handler是否有变,有变抛出异常
                 */
                rd.validate(context, handler);
            }
            rd.mForgotten = false;
            /**
             * 返回mIIntentReceiver
             * 
             * 
             */
            return rd.getIIntentReceiver();
        }
    }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!