Android 静态广播和动态广播接收顺序

  之前记得专门看了一下动态广播和静态广播的接收顺序,但是没想到被别人问的时候一口说错了,看来必须得理解了才能记住!

  看到知乎上面有人的回答自己也就顺便看了下ActivityManagerService源码broadcastIntentLocked方法:


 主要有下面几部分:

1.处理粘性广播

        if (sticky) {
           ......权限检查相关
            ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
            if (list == null) {
                list = new ArrayList<Intent>();
                mStickyBroadcasts.put(intent.getAction(), list);//添加到粘性广播列表中
            }
            .......
        }
主要是一些粘性广告权限的检查,以及把这个广播添加到粘性广播队列中,这里插入队列以后经过查找可以发现最终调用的地方是在registerReceiver函数中通过getStickiesLocked调用:

public Intent registerReceiver(IApplicationThread caller,
            IIntentReceiver receiver, IntentFilter filter, String permission) {
            ..............
            List allSticky = null;

            // Look for any matching sticky broadcasts...
            Iterator actions = filter.actionsIterator();
            if (actions != null) {
                while (actions.hasNext()) {
                    String action = (String)actions.next();
                    allSticky = getStickiesLocked(action, filter, allSticky);
                }
            } else {
                allSticky = getStickiesLocked(null, filter, allSticky);
            }

            // The first sticky in the list is returned directly back to
            // the client.
            Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;

            if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
                    + ": " + sticky);

            if (receiver == null) {
                return sticky;
            }

           .......

            // Enqueue broadcasts for all existing stickies that match
            // this filter.
            if (allSticky != null) {
                ArrayList receivers = new ArrayList();
                receivers.add(bf);

                int N = allSticky.size();
                for (int i=0; i<N; i++) {
                    Intent intent = (Intent)allSticky.get(i);
                    BroadcastRecord r = new BroadcastRecord(intent, null,
                            null, -1, -1, null, receivers, null, 0, null, null,
                            false, true, true);
                    if (mParallelBroadcasts.size() == 0) {
                        scheduleBroadcastsLocked();
                    }
                    mParallelBroadcasts.add(r);
                }
            }

            return sticky;
        }
    }
如果这个广播已经触发的话会添加到  mStickyBroadcasts这里就可以直接找到,返回了 sticky,这里就是粘性广播,它可以保持Intent的原因,接下来继续看第二部分

2. 处理普通广播

        // Figure out who all will receive this broadcast.
        List receivers = null;//静态广播
        List<BroadcastFilter> registeredReceivers = null;//动态广播
        try {
            if (intent.getComponent() != null) {
                // Broadcast is going to one specific receiver class...
                ActivityInfo ai = AppGlobals.getPackageManager().
                    getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
                if (ai != null) {
                    receivers = new ArrayList();
                    ResolveInfo ri = new ResolveInfo();
                    ri.activityInfo = ai;
                    receivers.add(ri);//初始化
                }
            } else {
                // Need to resolve the intent to interested receivers...
                if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                         == 0) {
                    receivers =
                        AppGlobals.getPackageManager().queryIntentReceivers(
                                intent, resolvedType, STOCK_PM_FLAGS);
                }
                registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);<span style="font-family: Arial, Helvetica, sans-serif;">//初始化</span>

            }
        }
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        if (!ordered && NR > 0) {//处理普通广播
            // If we are not serializing this broadcast, then send the
            // registered receivers separately so they don't wait for the
            // components to be launched.
            BroadcastRecord r = new BroadcastRecord(intent, callerApp,
                    callerPackage, callingPid, callingUid, requiredPermission,
                    registeredReceivers, resultTo, resultCode, resultData, map,
                    ordered, sticky, false);
            if (DEBUG_BROADCAST) Slog.v(
                    TAG, "Enqueueing parallel broadcast " + r
                    + ": prev had " + mParallelBroadcasts.size());
            boolean replaced = false;
            if (replacePending) {
                for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
                    if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
                        if (DEBUG_BROADCAST) Slog.v(TAG,
                                "***** DROPPING PARALLEL: " + intent);
                        mParallelBroadcasts.set(i, r);
                        replaced = true;
                        break;
                    }
                }
            }
            if (!replaced) {
                mParallelBroadcasts.add(r);
                scheduleBroadcastsLocked();//分发广播
            }
            registeredReceivers = null;
            NR = 0;
        }
上面函数可以看到只有处理了registeredReceivers动态广播添加到mParallelBroadcasts队列中并且调用了scheduleBroadcastsLocked()来分发广播并且已经registeredReceivers 赋值为null了,到这里普通动态广播处理完了,所以普通的动态广播一定在静态广播之前接收到。

  private final void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
                + mBroadcastsScheduled);

        if (mBroadcastsScheduled) {
            return;
        }
        mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
        mBroadcastsScheduled = true;
    }
最终会调到:

private final void processNextBroadcast(boolean fromMsg) {
        synchronized(this) {
            BroadcastRecord r;

            if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
                    + mParallelBroadcasts.size() + " broadcasts, "
                    + mOrderedBroadcasts.size() + " ordered broadcasts");

            updateCpuStats();
            
            if (fromMsg) {
                mBroadcastsScheduled = false;
            }

            // First, deliver any non-serialized broadcasts right away.
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                r.dispatchTime = SystemClock.uptimeMillis();
                final int N = r.receivers.size();
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
                        + r);
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    if (DEBUG_BROADCAST)  Slog.v(TAG,
                            "Delivering non-ordered to registered "
                            + target + ": " + r);
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);//进行分发
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
                        + r);
            }
            ..............
}

3.有序广播处理

    <span style="white-space:pre">	</span>    // Merge into one list.
        int ir = 0;
        if (receivers != null) {//存在静态广播开始处理静态广播
<span>		</span>   .........
            int NT = receivers != null ? receivers.size() : 0;
            int it = 0;
            ResolveInfo curt = null;
            BroadcastFilter curr = null;
            while (it < NT && ir < NR) {
                if (curt == null) {
                    curt = (ResolveInfo)receivers.get(it);
                }
                if (curr == null) {
                    curr = registeredReceivers.get(ir);
                }
                if (curr.getPriority() >= curt.priority) { //这里是真正的给静态广播和动态广播排序可以看到同优先级的动态广播一定在静态广播之前
                    // Insert this broadcast record into the final list.
                    receivers.add(it, curr);
                    ir++;
                    curr = null;
                    it++;
                    NT++;
                } else {
                    // Skip to the next ResolveInfo in the final list.
                    it++;
                    curt = null;
                }
            }
        }
        while (ir < NR) {
            if (receivers == null) {
                receivers = new ArrayList();
            }
            receivers.add(registeredReceivers.get(ir));
            ir++;
        }

<span style="white-space:pre">	</span>     .............
         mOrderedBroadcasts.add(r);
         scheduleBroadcastsLocked();//最终也调用此方法发送广播
    
        }

        return BROADCAST_SUCCESS;
这里有两种情况一种是如果是有序广播的话registeredReceivers不为空,如果是普通广播的话registeredReceivers 已经为空了,会在这里真正的进行排序,从这里可以看出来

相同优先级的有序广播,动态广播实在静态之前接收到的。



 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值