[Android]有序广播是如何实现有序循环(五)
2017-08-26 20:46
363 查看
[Android]有序广播是如何实现有序循环(五)
Android有序广播是如何实现有序循环五平行广播的循环前面已经讲到过
有序广播是如何循环起来的
1 如何将有序广播BroadcastRecord 发送给动态注册的Receiver
2 对于静态注册的Receiver是如何有序循环的
BroadcastRecord 完整的发送
Overview
而对有序广播来说,==原则上每次processNextBroadcast()只会将BroadcastRecord发送给一个receiver而已。当然,此时摘下的receiver既有可能是动态注册的,也有可能是静态的==。
对于动态注册的receiver,目标进程处理完广播之后,会间接调用am.finishReceiver()向AMS发出反馈,关于这一步,前文在讲Args.run()时已有涉及,只是当时主要关心的是里面的receiver.onReceive()一句,现在我们要关心其中的receiver.setPendingResult()一句:
不论任何广播,在APK处理完后,都要通知到AMS做一些收尾工作.
1. 平行广播的循环前面已经讲到过
参考BroadcastQueue如何分发广播(四)
2. 有序广播是如何循环起来的?
2.1 如何将有序广播BroadcastRecord 发送给动态注册的Receiver?
重点是,有序广播是如何循环起来的?回顾 Ams中创建BroadcastRecord的代码,mReceivers集合中是有两种对象:ResolveInfo/BroadcastFilter
BroadcastFilter 即是动态注册的Receiver
if (nextReceiver instanceof BroadcastFilter) { // Simple case: this is a registered receiver who gets // a direct call. BroadcastFilter filter = (BroadcastFilter)nextReceiver; deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx); if (r.receiver == null || !r.ordered) { // The receiver has already finished, so schedule to // process the next one. r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked(); } else { if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { scheduleTempWhitelistLocked(filter.owningUid, brOptions.getTemporaryAppWhitelistDuration(), r); } } return; }
NOTE:
执行流程类似于平行广播,最终也会进入到LoadedApk.ReceiverDispatcher($Args)
区别在于:
deliverToRegisteredReceiverLocked(r, filter, /order/ r.ordered, recIdx) //
最终还是会进入到Args.run(){}
try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); // 注意,把自己设到BroadcastReceiver的mPendingResult域里了 receiver.setPendingResult(this); receiver.onReceive(mContext, intent); } catch (Exception e) {} if (receiver.getPendingResult() != null) { finish(); }
frameworks/base/core / java / android / content /BroadcastReceiver.java
if (mType == TYPE_COMPONENT) { ... } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { final IActivityManager mgr = ActivityManagerNative.getDefault(); sendFinished(mgr); }
mType 对于registed广播来说,在注册时就已经决定
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser) { super(resultCode, resultData, resultExtras, mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags()); mCurIntent = intent; mOrdered = ordered; }
frameworks/base/core / java / android / content /BroadcastReceiver.java
public void sendFinished(IActivityManager am) { synchronized (this) { ... mFinished = true; try { // 注册此处的区别,对于ordered广播,需要保留resultCode resultData,resultExtras, mAbortBroadcst等信息,而对于 // 并行广播,无须关注这些 if (mOrderedHint) { // 将广播结束的消息告知Ams am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras, mAbortBroadcast, mFlags); } else { // This broadcast was sent to a component; it is not ordered, // but we still need to tell the activity manager we are done. am.finishReceiver(mToken, 0, null, null, false, mFlags); } } catch (RemoteException ex) { } } }
ActivityManagerService.java
public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, int flags) { try { boolean doNext = false; BroadcastRecord r; synchronized(this) { BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0 ? mFgBroadcastQueue : mBgBroadcastQueue; // r = queue.getMatchingOrderedReceiver(who); if (r != null) { // finishReceiverLocked做善后工作,判断该节点是否还需要继续分发 doNext = r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, true); } } // if (doNext) { r.queue.processNextBroadcast(false); } } finally { } }
BroadcastQueue.java
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; // 这里为什么要做大量的置空操作? r.receiver = null; r.intent.setComponent(null); if (r.curApp != null && r.curApp.curReceiver == r) { r.curApp.curReceiver = null; } if (r.curFilter != null) { r.curFilter.receiverList.curBroadcast = null; } r.curFilter = null; r.curReceiver = null; r.curApp = null; mPendingBroadcast = null; // 保留上个receiver的操作结果 r.resultCode = resultCode; r.resultData = resultData; r.resultExtras = resultExtras; ... 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; }
思考:
这里为何要做大量的置空操作?
每次在deliverToRegisteredReceiverLocked,都会在BroadcastRecord保存当前receiver对应信息,
而当发送完成时置空,释放对之前Receiver对应的内存,
下次在deliver时,重置赋值,而且这些信息只对Ordered广播有效
思考:
最后的state 为什么要== APP_RECEIVE/ CALL_DONE_RECEIVE
针对ordered广播在deliver后,都会重置状态,表示该节点的发送状态;当在finish时重置r.state = Idle,以便将此records分发给下一个receiver.
总结:
==至此,一个动态receive的接收就结束了==
2.2 对于静态注册的Receiver是如何有序循环的?
// 对于静态广播的接收是由ActivityThread来分发的private void handleReceiver(ReceiverData data) { . . . . . . IActivityManager mgr = ActivityManagerNative.getDefault(); BroadcastReceiver receiver; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); data.intent.setExtrasClassLoader(cl); data.setExtrasClassLoader(cl); receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); } catch (Exception e) { . . . . . . } try { . . . . . . receiver.setPendingResult(data); receiver.onReceive(context.getReceiverRestrictedContext(), data.intent); } catch (Exception e) { . . . . . . } finally { sCurrentBroadcastIntent.set(null); } if (receiver.getPendingResult() != null) { data.finish(); } }
ActivityThread.java
public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, IBinder token, int sendingUser) { super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token, sendingUser, intent.getFlags()); this.intent = intent; }
BroadcastReceiver.java
public final void finish() { if (mType == TYPE_COMPONENT) { final IActivityManager mgr = ActivityManagerNative.getDefault(); if (QueuedWork.hasPendingWork()) { ... } else { sendFinished(mgr); } } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { ... } }
==至此,静态receiver的完整分发流程结束==
总结:
receiver分发完成后,若是需要发送下一个receiver,依然是要回到processNextBroadcast(),而每次process只能发送到一个receiver
3. BroadcastRecord 完整的发送
如何将Broadcast完整的发送给所有的receiverdo{ int numReceivers = (r.receivers != null) ? r.receivers.size() : 0; // nextReceiver > numReceivers,即表示发送到了该节点的最后一条 if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { // No more receivers for this broadcast! Send the final // result if requested... cancelBroadcastTimeoutLocked(); // 添加到Broadcast 记录 addBroadcastToHistoryLocked(r); if (r.intent.getComponent() == null && r.intent.getPackage() == null && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { // This was an implicit broadcast... let's record it for posterity. mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage, r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime); } // 并且需要将这个操作完成的节点,从list中移除 mOrderedBroadcasts.remove(0); r = null; looped = true; continue; } } while ( r != null)
总结:
==当执行到此处表示最后一个receive也分发完成,需要将该节点移除,并处理下一个节点==
相关文章推荐
- 如何实现一个只有广播和service的android应用没有activity
- Android 如何实现 焦点图的 无线循环滑动的状态?
- android有序广播的实现
- android 的viewpager如何实现左右循环
- 开发日志整理1【android Launcher如何实现多屏循环滑动】
- android中如何实现循环更新UI
- Android实现发送一条有序广播
- 如何实现图片的无缝循环向上,下,右滚动
- 如何实现一个循环队列
- 如何实现一个循环缓冲区模型
- 如何实现一个循环队列
- 如何实现自己开发的网上实时电视广播系统?为你提供软
- 如何实现一个循环队列
- 如何实现一个循环缓冲区模型
- android 如何实现EditText从不可编辑状态变成可变成可编辑状态
- Android如何实现全屏现实
- 如何实现一个循环队列
- 如何实现一个循环缓冲区模型
- 如何实现一个循环缓冲区模型