BroadcastReceiver广播的注册、发送和接收过程分析

1. 简介

广播作为Android的四大组件之一,能够实现组件之间的通信。广播过程主要就是注册、发送和接收过程。广播使用了设计模式中的观察者模式:基于消息的发布 / 订阅事件模型,消息的生产者发布事件,而使用者订阅感兴趣的事件。因此,广播能够实现组件间的松耦合,即广播的发送者和接收者事先是可以不用知道对方存在的。接下来,我们来研究一下广播的注册、发送和接收过程的源码。

本文源码基于android 27

2.广播的注册过程

我们都知道,广播的注册分成两种:静态注册动态注册。静态注册通过在AndroidManifest.xml中注册广播接收者,应用安装时PackageManagerService通过解析AndroidManifest.xml来完成这个过程,由于涉及到PackageManagerService,这里暂且不表,后面再去分析PackageManagerService。我们这里来看下动态注册的过程,要实现动态注册需要调用registerReceiver()方法,其具体实现位于ContextWrapper类中。

2.1 ContextWrapper的registerReceiver

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

上面的mBase实际上是ContextImplContext类是个抽象类,ContextImpl类是Context类的具体实现,而ContextWrapper类是个装饰者的角色,这里涉及了装饰者模式,对装饰者模式有兴趣的可以看下这篇文章:装饰者模式
mBase是在Activity启动时被赋值的,这里就不祥说了。
我们来看下ContextImpl类的实现:

2.2 ContextImpl的registerReceiver

    @Override
    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(), 0);
    }

最终会调用registerReceiverInternal()

2.3 ContextImpl的registerReceiverInternal

   private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
   
        IIntentReceiver rd = null;
        if (receiver != null) {
   
            if (mPackageInfo != null && context != null) {
   
                if (scheduler == null) {
   
                    scheduler = mMainThread.getHandler();
                }
                //mPackageInfo的类型为LoadedApk类
                //如果mPackageInfo和context都不为空,则从mPackageInfo中获取IIntentReceiver对象
                //mPackageInfo.getReceiverDispatcher()最终还是通过LoadedApk.ReceiverDispatcher.getIIntentReceiver()来获取IIntentReceiver对象
                //详见下一小节的代码分析
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
   
                if (scheduler == null) {
   
                    scheduler = mMainThread.getHandler();
                }
                //如果mPackageInfo或context为空,则新创建一个ReceiverDispatcher对象并获取IIntentReceiver
                //IIntentReceiver的具体实现是在LoadedApk.ReceiverDispatcher.InnerReceiver中
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {
   
            //ActivityManager.getService()获取到的就是AMS,所以最终会调用到AMS的registerReceiver()方法
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            if (intent != null) {
   
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
   
            throw e.rethrowFromSystemServer();
        }
    }

从上面的代码可以看到,首先会获取到一个名为rdIIntentReceiver对象。如果mPackageInfocontext都不为空,则从mPackageInfo.getReceiverDispatcher()中获取;否则从LoadedApk.ReceiverDispatcher.InnerReceiver()中获取。

最后会将这个IIntentReceiver对象传递到AMS中去注册。

我们先来看看mPackageInfo.getReceiverDispatcher(),其具体实现是在LoadedApk类中:

2.4 LoadedApk的getReceiverDispatcher

    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) {
   
                    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);
                    }
                    map.put(r, rd);
                }
            } else {
   
                rd.validate(context, handler);
            }
            rd
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值