11.2.6 Activity Idle状态的处理过程
Activity执行onResume后会向主线程的消息队列注册IdleHandler,本例中注册的是Idler对象,当消息循环中没有其他消息需要处理时,消息处理器便会执行Idler的queueIdle方法,有关消息的调度和处理,请参考第7章。这里直接分析queueIdle方法,代码如下:
public final class ActivityThread{
……
private class Idler implements MessageQueue.IdleHandler{
public final boolean queueIdle(){
ActivityClientRecord a=mNewActivities;
……
if(a!=null){
mNewActivities=null;
//返回ActivityManagerProxy
IActivityManager am=ActivityManagerNative.getDefault();
ActivityClientRecord prev;
do{
if(a.activity!=null&&!a.activity.mFinished){
try{
//调用ActivityManagerProxy.activityIdle方法
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig=null;
}catch(RemoteException ex){
//忽略
}
}
prev=a;
a=a.nextIdle;
prev.nextIdle=null;
}while(a!=null);
}
……
return false;
}
}
Idler是ActivityThread的内部类,运行于应用程序主线程,其通过ActivityManagerNative.getDefault方法返回ActivityManagerProxy,进而调用其activityIdle方法。
ActivityManagerProxy是ActivityManagerService的BinderProxy,因此这里最终将调用ActivityManagerService的activityIdle方法,代码如下:
public final void activityIdle(IBinder token, Configuration config,
boolean stopProfiling){
final long origId=Binder.clearCallingIdentity();
//mMainStack即ActivityStack
ActivityRecord r=mMainStack.activityIdleInternal(token, false, config);
……
Binder.restoreCallingIdentity(origId);
}
ActivityManagerService将请求转发给ActivityStack.activityIdleInternal方法,代码如下:
final ActivityRecord activityIdleInternal(IBinder token,
boolean fromTimeout, Configuration config){
……
synchronized(mService){
ActivityRecord r=ActivityRecord.forToken(token);
if(r!=null){
//从ActivityStack的消息队列中移除IDLE_TIMEOUT_MSG消息
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
}
int index=indexOfActivityLocked(r);
if(index>=0){
res=r;
if(fromTimeout){
reportActivityLaunchedLocked(fromTimeout, r,-1,-1);
}
……
}else if(fromTimeout){
reportActivityLaunchedLocked(fromTimeout, null,-1,-1);
}
/*获取mStoppingActivities中存储的待停止的Activity,暂停
阶段由completePauseLocked方法将源Activity存入该列表/
stops=processStoppingActivitiesLocked(true);
……
}
……
//启动目标Activity启动会导致停止其他Activity,包括源Activity
for(i=0;i<NS;i++){
ActivityRecord r=(ActivityRecord)stops.get(i);
synchronized(mService){
if(r.finishing){
/*如果源Activity处于finishing状态,需要调用其onDestroy方
法,通常发生在源Activity在onPause方法中调用了finish方法/
finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
}else{
//否则直接调用源Activity的onStop方法
stopActivityLocked(r);
}
}
}
//启动目标Activity可能导致需要回收其他Activity
for(i=0;i<NF;i++){
ActivityRecord r=(ActivityRecord)finishes.get(i);
synchronized(mService){
activityRemoved=destroyActivityLocked(r, true, false,"finish-idle");
}
}
……
if(booting){//本例为false
mService.finishBooting();
}
mService.trimApplications();//回收应用程序进程,并更新OOM adj
……
if(activityRemoved){//本例为false
resumeTopActivityLocked(null);
}
return res;
}
activityIdleInternal方法有两个入口:ActivityThread和ActivityManagerService,由参数from Timeout标记。如果应用程序主线程在ActivityStack的IDLE_TIMEOUT_MSG消息指定的处理时间(10s)内调用了Idler对象的queueIdle方法,进而调用activityIdleInternal方法,fromTimeout参数为false;如果应用程序主线程在10s后仍未调用Idler对象的queueIdle方法,ActivityStack的消息处理器会处理IDLE_TIMEOUT_MSG消息,并直接调用activityIdleInternal方法,此时fromTimeout为true。
ActivityStack. activityIdleInternal方法的执行流程如下:
1)移除ActivityStack消息循环中的IDLE_TIMEOUT_MSG消息。不论入口点是ActivityThread或者ActivityManagerService, activityIdleInternal方法已经调用,因此不需要该消息了。
2)停止待停止列表中的Activity。这些Activity存储于ActivityStack.mStoppingActivities中,其中源Activity在暂停阶段由completePauseLocked方法存入待停止列表中。如果该列表中的Activity处于完成状态,则需要调用finishCurrentActivityLocked方法销毁该Activity,通常这种情况发生在pause方法中调用了finish方法。
3)销毁待销毁列表中的Activity。该过程由destroyActivityLocked方法完成,在12章中分析。
4)如果是系统启动阶段,即booting为true,此时需要调用finishBooting方法,在该方法中将会发送ACTION_BOOT_COMPLETED广播。本例非系统启动阶段,因此不执行这个步骤。
5)回收应用程序进程。该过程由trimApplications方法完成,将在第12章分析。
Activity在Idle状态一个最重要的操作便是停止待stop列表中的Activity,在这个步骤中将停止源Activity。