6.4.4 应用进程处理广播分析

下面来分析当应用进程收到广播后的处理流程,以动态接收者为例。

1.ApplicationThread scheduleRegisteredReceiver函数分析

如前所述,AMS将通过scheduleRegisteredReceiver函数将广播交给应用进程,该函数代码如下:

[—>ActivityThread.java:scheduleRegisteredReceiver]


public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,

int resultCode, String dataStr, Bundle extras, boolean ordered,

boolean sticky)throws RemoteException{

//又把receiver对象传了回来。还记得注册时传递的一个IIntentReceiver类型

//的对象吗?

receiver.performReceive(intent, resultCode, dataStr, extras, ordered,

sticky);

}


就本例而言,receiver对象的真实类型为LoadedApk.ReceiverDispatcher,来看它的performReceive函数,代码如下:

[—>LoadedApk.java:performReceive]


public void performReceive(Intent intent, int resultCode,

String data, Bundle extras, boolean ordered, boolean sticky){

//Args是一个runnable对象

Args args=new Args(intent, resultCode, data, extras, ordered, sticky);

//mActivityThread是一个Handler,还记得SDK提供的两个同名的registerReceiver

//函数吗?如果没有传递Handler,则使用主线程的Handler

if(!mActivityThread.post(args)){

if(mRegistered&&ordered){

IActivityManager mgr=ActivityManagerNative.getDefault();

args.sendFinished(mgr);

}

}

}


scheduleRegisteredReceiver最终向主线程的Handler投递了一个Args对象,这个对象的run函数将在主线程中被调用。

2.Args.run分析

这部分内容的代码如下:

[—>LoadedApk.java:Args.run]


public void run(){

final BroadcastReceiver receiver=mReceiver;

final boolean ordered=mOrdered;

final IActivityManager mgr=ActivityManagerNative.getDefault();

final Intent intent=mCurIntent;

mCurIntent=null;

……

try{

//获取ClassLoader对象,千万注意,此处并没有通过反射机制创建一个广播接收者,

//对于动态接收者来说,在注册前就已经创建完毕

ClassLoader cl=mReceiver.getClass().getClassLoader();

intent.setExtrasClassLoader(cl);

setExtrasClassLoader(cl);

receiver.setPendingResult(this);//设置pendingResult

//调用该动态接收者的onReceive函数

receiver.onReceive(mContext, intent);

}……

//调用finish完成工作

if(receiver.getPendingResult()!=null)finish();

}


Finish的代码很简单,此处不再赘述,在其内部会通过sendFinished函数调用AMS的finishReceiver函数,以通知AMS。

3.AMS的finishReceiver函数分析

不论是ordered还是非ordered广播,AMS的finishReceiver函数都会被调用,它的代码如下:

[—>ActivityManagerService.java:finishReceiver]


public void finishReceiver(IBinder who, int resultCode, String resultData,

Bundle resultExtras, boolean resultAbort){

……

boolean doNext;

final long origId=Binder.clearCallingIdentity();

synchronized(this){

//判断是否还需要继续调度后续的广播发送

doNext=finishReceiverLocked(

who, resultCode, resultData, resultExtras, resultAbort, true);

}

if(doNext){//发起下一次广播发送

processNextBroadcast(false);

}

trimApplications();

Binder.restoreCallingIdentity(origId);

}


由以上代码可知,finishReceiver将根据情况调度下一次广播发送。