品茗论道说广播(Broadcast内部机制讲解)(下)

品茗论道说广播(Broadcast内部机制讲解)(下)

 

侯 亮



       下面我们来看,递送广播动作中最重要的processNextBroadcast()。

 

3.2 最重要的processNextBroadcast()

        从processNextBroadcast()的代码,我们就可以看清楚前面说的“平行广播”、“有序广播”和“动态receiver”、“静态receiver”之间的关系了。

        我们在前文已经说过,所有的静态receiver都是串行处理的,而动态receiver则会按照发广播时指定的方式,进行“并行”或“串行”处理。能够并行处理的广播,其对应的若干receiver一定都已经存在了,不会牵扯到启动新进程的操作,所以可以在一个while循环中,一次性全部deliver。而有序广播,则需要一个一个地处理,其滚动处理的手段是发送事件,也就是说,在一个receiver处理完毕后,会利用广播队列(BroadcastQueue)的mHandler,发送一个BROADCAST_INTENT_MSG事件,从而执行下一次的processNextBroadcast()。

        processNextBroadcast()的代码逻辑大体是这样的:先尝试处理BroadcastQueue中的“平行广播”部分。这需要遍历并行列表(mParallelBroadcasts)的每一个BroadcastRecord以及其中的receivers列表。对于平行广播而言,receivers列表中的每个子节点是个BroadcastFilter。我们直接将广播递送出去即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while  (mParallelBroadcasts.size() >  0
{
     r = mParallelBroadcasts.remove( 0 );
     r.dispatchTime = SystemClock.uptimeMillis();
     r.dispatchClockTime = System.currentTimeMillis();
     final  int  N = r.receivers.size();
     . . . . . . 
     for  ( int  i= 0 ; i<N; i++) 
     {
         Object target = r.receivers.get(i);
         . . . . . .
         deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target,  false );
     }
     . . . . . .
}

 

3.2.1 用deliverToRegisteredReceiverLocked()递送到平行动态receiver

        deliverToRegisteredReceiverLocked()的代码截选如下:

【frameworks/base/services/java/com/android/server/am/BroadcastQueue.java】

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private  final  void  deliverToRegisteredReceiverLocked(BroadcastRecord r,
                                                      BroadcastFilter filter, 
                                                      boolean  ordered) 
{
     . . . . . .
     . . . . . .
     if  (!skip) 
     {
         if  (ordered) 
         {
             r.receiver = filter.receiverList.receiver.asBinder();
             r.curFilter = filter;
             filter.receiverList.curBroadcast = r;
             r.state = BroadcastRecord.CALL_IN_RECEIVE;
             if  (filter.receiverList.app !=  null
             {
                 r.curApp = filter.receiverList.app;
                 filter.receiverList.app.curReceiver = r;
                 mService.updateOomAdjLocked();
             }
         }
         
             . . . . . .
             performReceiveLocked(filter.receiverList.app, 
                                  filter.receiverList.receiver,
                                  new  Intent(r.intent), r.resultCode,
                                  r.resultData, r.resultExtras, 
                                  r.ordered, r.initialSticky);
             if  (ordered) 
             {
                 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
             }
         
         . . . . . .
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private  static  void  performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
         Intent intent,  int  resultCode, String data, Bundle extras,
         boolean  ordered,  boolean  sticky)  throws  RemoteException 
{
     // Send the intent to the receiver asynchronously using one-way binder calls.
     if  (app !=  null  && app.thread !=  null
     {
         // If we have an app thread, do the call through that so it is
         // correctly ordered with other one-way calls.
         app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                 data, extras, ordered, sticky);
    
     else 
     {
         receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
     }
}

终于通过app.thread向用户进程传递语义了。注意scheduleRegisteredReceiver()的receiver参数,它对应的就是前文所说的ReceiverDispatcher的Binder实体——InnerReceiver了。

        总之,当语义传递到用户进程的ApplicationThread以后,走到:

?
1
2
3
4
5
6
7
8
9
// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public  void  scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
         int  resultCode, String dataStr, Bundle extras,  boolean  ordered,
         boolean  sticky)  throws  RemoteException 
{
     receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
}

终于走到ReceiverDispatcher的InnerReceiver了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
static  final  class  ReceiverDispatcher 
{
     final  static  class  InnerReceiver  extends  IIntentReceiver.Stub 
     {
         . . . . . .
         . . . . . .
         public  void  performReceive(Intent intent,  int  resultCode,
                                    String data, Bundle extras, 
                                    boolean  ordered,  boolean  sticky) 
         {
             LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
             . . . . . .
             if  (rd !=  null ) {
                 rd.performReceive(intent, resultCode, data, extras,
                                   ordered, sticky);
            
             . . . . . .
         }
     }
     . . . . . .
     public  void  performReceive(Intent intent,  int  resultCode,
                                String data, Bundle extras, 
                                boolean  ordered,  boolean  sticky) 
     {
         . . . . . .
         Args args =  new  Args(intent, resultCode, data, extras, ordered, sticky);
         if  (!mActivityThread.post(args))  // 请注意这一句!
         {
             if  (mRegistered && ordered) 
             {
                 IActivityManager mgr = ActivityManagerNative.getDefault();
                 if  (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                         "Finishing sync broadcast to "  + mReceiver);
                 args.sendFinished(mgr);
             }
         }
     }
}

请注意mActivityThread.post(args)一句,这样,事件泵最终会回调Args参数的run()成员函数:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
final  class  Args  extends  BroadcastReceiver.PendingResult  implements  Runnable 
{
     . . . . . .
     . . . . . .
     public  void  run() 
     {
         final  BroadcastReceiver receiver = mReceiver;
         . . . . . .
         try  {
             ClassLoader cl =  mReceiver.getClass().getClassLoader();
             intent.setExtrasClassLoader(cl);
             setExtrasClassLoader(cl);
             receiver.setPendingResult( this );
             receiver.onReceive(mContext, intent);   // 回调具体receiver的onReceive()
         catch  (Exception e) {
             . . . . . .
         }
         
         if  (receiver.getPendingResult() !=  null ) {
             finish();
         }
         . . . . . .
     }
}

其中的那句receiver.onReceive(this),正是回调我们具体receiver的onReceive()成员函数的地方。噢,终于看到应用程序员熟悉的onReceive()了。这部分的示意图如下:


3.2.2 静态receiver的递送

        说完动态递送,我们再来看静态递送。对于静态receiver,情况会复杂很多,因为静态receiver所从属的进程有可能还没有运行起来呢。此时BroadcastRecord节点中记录的子列表的节点是ResolveInfo对象。

?
1
2
3
4
ResolveInfo info = (ResolveInfo)nextReceiver;
. . . . . .
r.state = BroadcastRecord.APP_RECEIVE;
String targetProcess = info.activityInfo.processName;

那么我们要先找到receiver所从属的进程的进程名。

         processNextBroadcast()中启动进程的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ProcessRecord app = mService.getProcessRecordLocked(targetProcess, 
info.activityInfo.applicationInfo.uid);
. . . . . .
if  (app !=  null  && app.thread !=  null
{
     . . . . . .
     app.addPackage(info.activityInfo.packageName);
     processCurBroadcastLocked(r, app);
     return ;
     . . . . . .
}
r.curApp = mService.startProcessLocked(targetProcess,
                                info.activityInfo.applicationInfo,  true ,
                                r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                                "broadcast" , r.curComponent,              
                                (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) !=  0
                                false )
. . . . . .
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;

        如果目标进程已经存在了,那么app.thread肯定不为null,直接调用processCurBroadcastLocked()即可,否则就需要启动新进程了。启动的过程是异步的,可能很耗时,所以要把BroadcastRecord节点记入mPendingBroadcast。

3.2.2.1 processCurBroadcastLocked()

        我们先说processCurBroadcastLocked()。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private  final  void  processCurBroadcastLocked(BroadcastRecord r,
                         ProcessRecord app)  throws  RemoteException 
{
     . . . . . .
     r.receiver = app.thread.asBinder();
     r.curApp = app;
     app.curReceiver = r;
     . . . . . .
     . . . . . .
         app.thread.scheduleReceiver( new  Intent(r.intent), r.curReceiver,
               mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
               r.resultCode, r.resultData, r.resultExtras, r.ordered);
         . . . . . .
         started =  true ;
     . . . . . .
}

其中最重要的是调用app.thread.scheduleReceiver()的那句。在IApplicationThread接口中,是这样定义scheduleReceiver()函数原型的:

?
1
2
3
4
5
void  scheduleReceiver(Intent intent, ActivityInfo info, 
                       CompatibilityInfo compatInfo,                      
                       int  resultCode, String data, 
                       Bundle extras,  boolean  sync) 
                       throws  RemoteException;

其中ActivityInfo info参数,记录着目标receiver的信息。可以看到,递送静态receiver时,是不会用到RecevierDispatcher的。

        用户进程里handleMessage()

?
1
2
3
4
5
6
case  RECEIVER:
     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,  "broadcastReceiveComp" );
     handleReceiver((ReceiverData)msg.obj);
     maybeSnapshot();
     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);    
     break ;

        ActivityThread中,会运用反射机制,创建出BroadcastReceiver对象,而后回调该对象的onReceive()成员函数。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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();
     }
}
3.2.2.2 必要时启动新进程

        现在我们回过头来看,在目标进程尚未启动的情况下,是如何完成递送的。刚刚我们已经看到调用startProcessLocked()的句子了,只要不出问题,目标进程成功启动后就会调用AMS的attachApplication()。

        有关attachApplication()的详情,请参考其他关于AMS的文档,此处我们只需知道它里面又会调用attachApplicationLocked()函数。

?
1
private  final  boolean  attachApplicationLocked(IApplicationThread thread,  int  pid)

attachApplicationLocked()内有这么几句:

?
1
2
3
4
5
6
7
8
9
// Check if a next-broadcast receiver is in this process...
if  (!badApp && isPendingBroadcastProcessLocked(pid)) {
     try  {
         didSomething = sendPendingBroadcastsLocked(app);
     catch  (Exception e) {
         // If the app died trying to launch the receiver we declare it 'bad'
         badApp =  true ;
     }
}

它们的意思是,如果新启动的进程就是刚刚mPendingBroadcast所记录的进程的话,此时AMS就会执行sendPendingBroadcastsLocked(app)一句。

 

?
1
2
3
4
5
6
7
8
// The app just attached; send any pending broadcasts that it should receive
boolean  sendPendingBroadcastsLocked(ProcessRecord app) {
     boolean  didSomething =  false ;
     for  (BroadcastQueue queue : mBroadcastQueues) {
         didSomething |= queue.sendPendingBroadcastsLocked(app);
     }
     return  didSomething;
}

BroadcastQueue的sendPendingBroadcastsLocked()函数如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public  boolean  sendPendingBroadcastsLocked(ProcessRecord app) {
     boolean  didSomething =  false ;
     final  BroadcastRecord br = mPendingBroadcast;
     if  (br !=  null  && br.curApp.pid == app.pid) {
         try  {
             mPendingBroadcast =  null ;
             processCurBroadcastLocked(br, app);
             didSomething =  true ;
         catch  (Exception e) {
             . . . . . .
         }
     }
     return  didSomething;
}

可以看到,既然目标进程已经成功启动了,那么mPendingBroadcast就可以赋值为null了。接着,sendPendingBroadcastsLocked()会调用前文刚刚阐述的processCurBroadcastLocked(),其内再通过app.thread.scheduleReceiver(),将语义发送到用户进程,完成真正的广播递送。这部分在上一小节已有阐述,这里就不多说了。

 

3.2.3 说说有序广播是如何循环起来的?

        我们知道,平行广播的循环很简单,只是在一个while循环里对每个动态receiver执行deliverToRegisteredReceiverLocked()即可。而对有序广播来说,原则上每次processNextBroadcast()只会处理一个BroadcastRecord的一个receiver而已。当然,此时摘下的receiver既有可能是动态注册的,也有可能是静态的。

        对于动态注册的receiver,目标进程处理完广播之后,会间接调用am.finishReceiver()向AMS发出反馈,关于这一步,其实在前面罗列ReceiverDispatcher的performReceive()时已经出现过了,我们再列一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  void  performReceive(Intent intent,  int  resultCode,
                            String data, Bundle extras, 
                            boolean  ordered,  boolean  sticky) 
{
     . . . . . .
     Args args =  new  Args(intent, resultCode, data, extras, ordered, sticky);
     if  (!mActivityThread.post(args)) 
     {
         if  (mRegistered && ordered) 
         {
             IActivityManager mgr = ActivityManagerNative.getDefault();
             . . . . . .
             args.sendFinished(mgr);   // 请注意这一句!
         }
     }
}

Args继承于BroadcastReceiver.PendingResult,它调用的sendFinished()就是PendingResult的sendFinished():

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public  void  sendFinished(IActivityManager am) 
{
     synchronized  ( this ) {
         if  (mFinished) {
             throw  new  IllegalStateException( "Broadcast already finished" );
         }
         mFinished =  true ;
     
         try  {
             if  (mResultExtras !=  null ) {
                 mResultExtras.setAllowFds( false );
             }
             if  (mOrderedHint) {
                 am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                         mAbortBroadcast);
             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 );
             }
         catch  (RemoteException ex) {
         }
     }
}

代码中的am.finishReceiver()会通知AMS,表示用户侧receiver已经处理好了,或者至少告一段落了,请AMS进行下一步动作。

        而对于动态注册的receiver,情况是类似的,最终也是调用am.finishReceiver()向AMS发出回馈的,只不过发起的动作是在ActivityThread的handleReceiver()动作中。前文已经列过这个函数了,大家注意下面的句子即可:

?
1
2
3
4
5
6
7
8
9
10
11
private  void  handleReceiver(ReceiverData data) 
{
         . . . . . .
         receiver.setPendingResult(data);
         receiver.onReceive(context.getReceiverRestrictedContext(),
                 data.intent);
         . . . . . .
     if  (receiver.getPendingResult() !=  null ) {
         data.finish();
     }
}

ReceiverData也是继承于BroadcastReceiver.PendingResult的,它调用的finish()是PendingResult的finish():

?
1
2
3
4
5
6
7
8
9
10
11
public  final  void  finish() 
{
     if  (mType == TYPE_COMPONENT) {
         . . . . . .
     else  if  (mOrderedHint && mType != TYPE_UNREGISTERED) {
         if  (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                 "Finishing broadcast to "  + mToken);
         final  IActivityManager mgr = ActivityManagerNative.getDefault();
         sendFinished(mgr);
     }
}

此处的sendFinished()内部最终也会调用到am.finishReceiver(),向AMS通告receiver已经处理好了。

         AMS侧在收到finishReceiver语义后,执行:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public  void  finishReceiver(IBinder who,  int  resultCode, String resultData,
         Bundle resultExtras,  boolean  resultAbort) 
{
     . . . . . .
     try  {
         boolean  doNext =  false ;
         BroadcastRecord r =  null ;
         synchronized ( this ) {
             r = broadcastRecordForReceiverLocked(who);
             if  (r !=  null ) {
                 doNext = r.queue.finishReceiverLocked(r, resultCode,
                     resultData, resultExtras, resultAbort,  true );
             }
         }
         if  (doNext) {
             r.queue.processNextBroadcast( false );
         }
         trimApplications();
     finally  {
         Binder.restoreCallingIdentity(origId);
     }
}

可以看到,如有必要,会继续调用processNextBroadcast(),从而完成有序广播的循环处理。

 

3.2.4 说说有序广播的timeout处理

        因为AMS很难知道一次广播究竟能不能完全成功递送出去,所以它必须实现一种“时限机制”。前文在阐述broadcastIntentLocked()时,提到过new一个BroadcastRecord节点,并插入一个BroadcastQueue里的“平行列表”或者“有序列表”。不过当时我们没有太细说那个BroadcastQueue,现在我们多加一点儿说明。

        实际上系统中有两个BroadcastQueue,一个叫做“前台广播队列”,另一个叫“后台广播队列”,在AMS里是这样定义的:

?
1
2
BroadcastQueue mFgBroadcastQueue;
BroadcastQueue mBgBroadcastQueue;

为什么要搞出两个队列呢?我认为这是因为系统对“广播时限”的要求不同导致的。对于前台广播队列而言,它里面的每个广播必须在10秒之内把广播递送给receiver,而后台广播队列的时限比较宽,只需60秒之内递送到就可以了。具体时限值请看BroadcastQueue的mTimeoutPeriod域。注意,这个10秒或60秒限制是针对一个receiver而言的。比方说“前台广播队列”的某个BroadcastRecord节点对应了3个receiver,那么在处理这个广播节点时,只要能在30秒(3 x 10)之内搞定就可以了。事实上,AMS系统考虑了更多东西,所以它给一个BroadcastRecord的总时限是其所有receiver时限之和的2倍,在此例中就是60秒(2 x 3 x 10)。

        对于平行receiver而言,时限的作用小一点儿,因为动态receiver是直接递送到目标进程的,它不考虑目标端是什么时候处理完这个广播的。

        然而对于有序receiver来说,时限就比较重要了。因为receiver之间必须是串行处理的,也就是说上一个receiver在没处理完时,系统是不会让下一个receiver进行处理的。从processNextBroadcast()的代码来看,在处理有序receiver时,BroadcastRecord里的nextReceiver域会记录“下一个应该处理的receiver”的标号。只有在BroadcastRecord的所有receiver都处理完后,或者BroadcastRecord的处理时间超过了总时限的情况下,系统才会把这个BroadcastRecord节点从队列里删除。因此我们在processNextBroadcast()里看到的获取当前BroadcastRecord的句子是写死为r = mOrderedBroadcasts.get(0)的。


        在拿到当前BroadcastRecord之后,利用nextReceiver值拿到当前该处理的receiver信息:

?
1
2
3
int  recIdx = r.nextReceiver++;
. . . . . .
Object nextReceiver = r.receivers.get(recIdx);

当然,一开始,nextReceiver的值只会是0,表示第一个receiver有待处理,此时会给BroadcastRecord的dispatchTime域赋值。

?
1
2
3
4
5
6
int  recIdx = r.nextReceiver++;
r.receiverTime = SystemClock.uptimeMillis(); if  (recIdx ==  0 ) {
     r.dispatchTime = r.receiverTime;
     r.dispatchClockTime = System.currentTimeMillis();
     . . . . . .
}

也就是说,dispatchTime的意义是标记实际处理BroadcastRecord的起始时间,那么这个BroadcastRecord所能允许的最大时限值就是:

dispatchTime + 2 * mTimeoutPeriod * 其receiver总数

一旦超过这个时限,而BroadcastRecord又没有处理完,那么就强制结束这个BroadcastRecord节点:

?
1
2
3
4
5
6
7
8
if  ((numReceivers >  0 ) &&
         (now > r.dispatchTime + ( 2 *mTimeoutPeriod*numReceivers))) 
{
     . . . . . .
     broadcastTimeoutLocked( false );  // forcibly finish this broadcast
     forceReceive =  true ;
     r.state = BroadcastRecord.IDLE;
}

此处调用的broadcastTimeoutLocked()的参数是boolean fromMsg,表示这个函数是否是在处理“时限消息”的地方调用的,因为当前是在processNextBroadcast()函数里调用broadcastTimeoutLocked()的,所以这个参数为false。从这个参数也可以看出,另一处判断“处理已经超时”的地方是在消息处理机制里,在那个地方,fromMsg参数应该设为true。

        大体上说,每当processNextBroadcast()准备递送receiver时,会调用setBroadcastTimeoutLocked()设置一个延迟消息:

?
1
2
3
long  timeoutTime = r.receiverTime + mTimeoutPeriod;
. . . . . .
setBroadcastTimeoutLocked(timeoutTime);

setBroadcastTimeoutLocked()的代码如下:

?
1
2
3
4
5
6
7
8
final  void  setBroadcastTimeoutLocked( long  timeoutTime) 
{     if  (! mPendingBroadcastTimeoutMessage) 
     {
         Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG,  this );
         mHandler.sendMessageAtTime(msg, timeoutTime);
         mPendingBroadcastTimeoutMessage =  true ;
     }
}

只要我们的receiver能及时处理广播,系统就会cancel上面的延迟消息。这也就是说,但凡事件泵的handleMessage()开始处理这个消息,就说明receiver处理超时了。此时,系统会放弃处理这个receiver,并接着尝试处理下一个receiver。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
final  Handler mHandler =  new  Handler() 
{
     public  void  handleMessage(Message msg) {
         switch  (msg.what) 
         {
             . . . . . .
             case  BROADCAST_TIMEOUT_MSG: 
             {
                 synchronized  (mService) 
                 {
                     broadcastTimeoutLocked( true );
                 }
             break ;
         }
     }
};

broadcastTimeoutLocked()的代码截选如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final  void  broadcastTimeoutLocked( boolean  fromMsg) 
{
     if  (fromMsg) {
         mPendingBroadcastTimeoutMessage =  false ;
     }
     if  (mOrderedBroadcasts.size() ==  0 ) {
         return ;
     }
     long  now = SystemClock.uptimeMillis();
     BroadcastRecord r = mOrderedBroadcasts.get( 0 );
     . . . . . .
     . . . . . .
     finishReceiverLocked(r, r.resultCode, r.resultData,
             r.resultExtras, r.resultAbort,  true );
     scheduleBroadcastsLocked();
     . . . . . .
}

可以看到,当一个receiver超时后,系统会放弃继续处理它,并再次调用scheduleBroadcastsLocked(),尝试处理下一个receiver。

 

4 尾声

        有关Android的广播机制,我们就先说这么多吧。品一杯红茶,说一段代码,管他云山雾罩,任那琐碎冗长,我自冷眼看安卓,瞧他修短随化。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悠然红茶

原来还有打赏功能,试一下呦。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值