Android广播机制实现源码浅析(二)

http://blog.csdn.net/hehui1860/article/details/30727075


紧接着上篇的分析,我们现在来分析一下处理广播的代码流程,也就是在方法queue.scheduleBroadcastsLocked();之后的操作
这些方法在BroadcastQueue.java中。在这里能看到我们常说的广播超时,以及我们重写onReceive什么时候执行。

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public void scheduleBroadcastsLocked() {  
  2.         if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["  
  3.                 + mQueueName + "]: current="  
  4.                 + mBroadcastsScheduled);  
  5.   
  6.         if (mBroadcastsScheduled) {  
  7.             return;  
  8.         }  
  9.         mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));  
  10.         mBroadcastsScheduled = true;  
  11. }  
  12.   
  13. final Handler mHandler = new Handler() {  
  14.         //public Handler() {  
  15.         //    if (localLOGV) Slog.v(TAG, "Handler started!");  
  16.         //}  
  17.   
  18.         public void handleMessage(Message msg) {  
  19.             switch (msg.what) {  
  20.                 case BROADCAST_INTENT_MSG: {  
  21.                     if (DEBUG_BROADCAST) Slog.v(  
  22.                             TAG, "Received BROADCAST_INTENT_MSG");  
  23.                     processNextBroadcast(true);  
  24.                 } break;  
  25.                 case BROADCAST_TIMEOUT_MSG: {  
  26.                     synchronized (mService) {  
  27.                         broadcastTimeoutLocked(true);  
  28.                     }  
  29.                 } break;  
  30.             }  
  31.         }  
  32. };  


可以看到这里在分发广播时直接post一个消息到队列中,不影响后面的此过程的后续操作,这说明发送和处理广播是一个异步操作,后面才是真正的处理过程。
[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. final void processNextBroadcast(boolean fromMsg) {  
  2. ……  
  3. // First, deliver any non-serialized broadcasts right away.  
  4.             while (mParallelBroadcasts.size() > 0) {  
  5.                 r = mParallelBroadcasts.remove(0);  
  6.                 r.dispatchTime = SystemClock.uptimeMillis();  
  7.                 r.dispatchClockTime = System.currentTimeMillis();  
  8.                 final int N = r.receivers.size();  
  9.                 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["  
  10.                         + mQueueName + "] " + r);  
  11.                 for (int i=0; i<N; i++) {  
  12.                     Object target = r.receivers.get(i);  
  13.                     if (DEBUG_BROADCAST)  Slog.v(TAG,  
  14.                             "Delivering non-ordered on [" + mQueueName + "] to registered "  
  15.                             + target + ": " + r);  
  16.                     deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);  
  17.                 }  
  18.                 addBroadcastToHistoryLocked(r);  
  19.                 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["  
  20.                         + mQueueName + "] " + r);  
  21.             }  
  22. ……  
  23. }  
  24.   
  25. 这里的先处理的是mParallelBroadcasts中的接收器,前文的分析中得知这个里面的接收器全部都是无序广播接收器中动态注册的,而静态注册的以及有序广播的都是在mOrderedBroadcasts中,本文先对无序动态的流程进行说明。  
  26. <pre name="code" class="html">private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,  
  27.             BroadcastFilter filter, boolean ordered) {  
  28. ……  
  29.             try {  
  30.                 if (DEBUG_BROADCAST_LIGHT) {  
  31.                     int seq = r.intent.getIntExtra("seq", -1);  
  32.                     Slog.i(TAG, "Delivering to " + filter  
  33.                             + " (seq=" + seq + "): " + r);  
  34.                 }  
  35.                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,  
  36.                     new Intent(r.intent), r.resultCode, r.resultData,  
  37.                     r.resultExtras, r.ordered, r.initialSticky, r.userId);  
  38.                 if (ordered) {  
  39.                     r.state = BroadcastRecord.CALL_DONE_RECEIVE;  
  40.                 }  
  41.             } catch (RemoteException e) {  
  42.                 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);  
  43.                 if (ordered) {  
  44.                     r.receiver = null;  
  45.                     r.curFilter = null;  
  46.                     filter.receiverList.curBroadcast = null;  
  47.                     if (filter.receiverList.app != null) {  
  48.                         filter.receiverList.app.curReceiver = null;  
  49.                     }  
  50.                 }  
  51.             }  
  52. }  
  53. private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,  
  54.             Intent intent, int resultCode, String data, Bundle extras,  
  55.             boolean ordered, boolean sticky, int sendingUser) throws RemoteException {  
  56.         // Send the intent to the receiver asynchronously using one-way binder calls.  
  57.         if (app != null && app.thread != null) {  
  58.             // If we have an app thread, do the call through that so it is  
  59.             // correctly ordered with other one-way calls.  
  60.             app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,  
  61.                     data, extras, ordered, sticky, sendingUser);  
  62.         } else {  
  63.             receiver.performReceive(intent, resultCode, data, extras, ordered,  
  64.                     sticky, sendingUser);  
  65.         }  
  66. }  
  67.   
  68.   
  69.   
  70. 这里的app.thread就是发送广播应用的ApplicationThreadProxy,这里用到了跨进程通信的知识,  
  71. 简要说一下,所有的应用进程在创建时就新建了一个activitythread和一个appliacationthread,前者用于处理主线程的用户交互操作和界面刷新操作。后者主要用户和system service进行跨进程的调用。  
  72. ApplicationThread是ActivityThread的一个内部类,所以接下来看文件ActivityThread.java中的  
  73. <pre name="code" class="html">public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,  
  74.                 int resultCode, String dataStr, Bundle extras, boolean ordered,  
  75.                 boolean sticky, int sendingUser) throws RemoteException {  
  76.             receiver.performReceive(intent, resultCode, dataStr, extras, ordered,  
  77.                     sticky, sendingUser);  
  78. }  

这里的receiver就是在广播注册过程中关联上的,它的实现是Loadedapk. ReceiverDispatcher. InnerReceiver,这个在动态注册广播时ContextImpl中的registerReceiverInternal方法中有体现,继续往下:
[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static final class ReceiverDispatcher {  
  2. final static class InnerReceiver extends IIntentReceiver.Stub {  
  3. public void performReceive(Intent intent, int resultCode, String data,  
  4.                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {  
  5.                  ……  
  6. If (rd != null) {  
  7.                     rd.performReceive(intent, resultCode, data, extras,  
  8.                             ordered, sticky, sendingUser);  
  9.                 }  
  10.                 ……..  
  11. }  
  12. }  
  13.   
  14.         public void performReceive(Intent intent, int resultCode, String data,  
  15.                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {  
  16.             if (ActivityThread.DEBUG_BROADCAST) {  
  17.                 int seq = intent.getIntExtra("seq", -1);  
  18.                 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq  
  19.                         + " to " + mReceiver);  
  20.             }  
  21.             Args args = new Args(intent, resultCode, data, extras, ordered,  
  22.                     sticky, sendingUser);  
  23.             if (!mActivityThread.post(args)) {  
  24.                 if (mRegistered && ordered) {  
  25.                     IActivityManager mgr = ActivityManagerNative.getDefault();  
  26.                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,  
  27.                             "Finishing sync broadcast to " + mReceiver);  
  28.                     args.sendFinished(mgr);  
  29.                 }  
  30.             }  
  31.         }  
  32.   
  33. final class Args extends BroadcastReceiver.PendingResult implements Runnable {  
  34. public void run() {  
  35.                ………  
  36. try {  
  37.                     ClassLoader cl =  mReceiver.getClass().getClassLoader();  
  38.                     intent.setExtrasClassLoader(cl);  
  39.                     setExtrasClassLoader(cl);  
  40.                     receiver.setPendingResult(this);  
  41.                     receiver.onReceive(mContext, intent);  
  42.                 } catch (Exception e) {  
  43.                     if (mRegistered && ordered) {  
  44.                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,  
  45.                                 "Finishing failed broadcast to " + mReceiver);  
  46.                         sendFinished(mgr);  
  47.                     }  
  48.                     if (mInstrumentation == null ||  
  49.                             !mInstrumentation.onException(mReceiver, e)) {  
  50.                         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  51.                         throw new RuntimeException(  
  52.                             "Error receiving broadcast " + intent  
  53.                             + " in " + mReceiver, e);  
  54.                     }  
  55.                 }  
  56.                   
  57.                 if (receiver.getPendingResult() != null) {  
  58.                     finish();  
  59.                 }  
  60. ……………  
  61. }  
  62. }  
  63. }  

 


 
这里mActivityThread成员变量的类型为Handler,它是前面动态注册广播接收器时,从ActivityThread取得的应用主线程的Handler,并把消息post到消息队列中去,因此,ReceiverDispatcher不等这个广播被应用处理就返回了,这里也体现了广播的发送和处理是异步进行的。 最终执行的是Args里面的run方法,在这里执行了注册时保存的BroadcastReceiver实例的onReceive方法。这样就完成了一次广播处理过程。 


说到这里我们分析了一个动态注册广播接收器处理非有序广播的过程,也留下了两个疑问,一个是静态广播以及有序广播的处理过程,还有一个就是前面提到的广播超时问题没有说明,下篇将对这两个问题进行继续分析。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值