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将根据情况调度下一次广播发送。