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。