11.2.2 暂停

启动应用程序Activity的第二个阶段是暂停(Pause),该阶段的主要工作是暂停启动目标Activity的源Activity,本例中即暂停Launcher。暂停阶段由六个主要步骤组成,接下来详细分析各个步骤。

1.ActivityStack.startPausingLocked

暂停阶段的第一步由ActivityStack.startPausingLocked方法完成,代码如下:


private final void startPausingLocked(boolean userLeaving,

boolean uiSleeping){//uiSleeping为false

if(mPausingActivity!=null){//本例为null,此时还没确定需要暂停的Activity

……//已经有需要暂停的Activity,打印异常,但不返回

}

//本例中prev是Launcher的ActivityRecord

ActivityRecord prev=mResumedActivity;

//没有处于Resume状态的Activity,启动栈顶Activity并返回

if(prev==null){

resumeTopActivityLocked(null);

return;

}

mResumedActivity=null;//将当前resume状态的activity赋值为null

mPausingActivity=prev;//设置当前要暂停的Activity为Launcher

mLastPausedActivity=prev;//设置上次暂停的Activity为Launcher

prev.state=ActivityState.PAUSING;//更改Launcher状态为正在暂停

……

/*prev.app即ProcessRecord,本例中表示Launcher的进程信息,prev.app.thread即

ApplicationThreadProxy,可以访问Launcher主线程/

if(prev.app!=null&&prev.app.thread!=null){//满足条件

try{

//prev.appToken为IApplicationToken.Stub, finishing为false,异步执行

prev.app.thread.schedulePauseActivity(prev.appToken,

prev.finishing,……);//userLeaving为true

……

}catch(Exception e){

}

}else{

mPausingActivity=null;

mLastPausedActivity=null;

}

/非休眠和关机状态时,在Activity启动前需要保持设备处于唤醒(awake)状态/

if(!mService.mSleeping&&!mService.mShuttingDown){//满足该条件

mLaunchingActivity.acquire();//获得WakeLock

//不能持有WakeLock太长时间,发送超时处理消息

if(!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)){//满足

Message msg=mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);

mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);

}

}

if(mPausingActivity!=null){//此时为Launcher

if(!uiSleeping){//传入参数为false,满足该分支

//在新Activity启动前,暂停key dispatch事件

prev.pauseKeyDispatchingLocked();

}else{//屏幕关闭状态下,不需要暂停key dispatch事件

}

//暂停一个Activity也需要指定超时处理,防止无响应,在本例中执行以下代码后返回

Message msg=mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);

msg.obj=prev;

prev.pauseTime=SystemClock.uptimeMillis();

mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);

}else{

//如果Pause操作失败,只需要启动栈顶Activity

resumeTopActivityLocked(null);

}

}


暂停阶段第一步的主要工作如下:

记录当前将要暂停的Activity。

通过schedulePauseActivity方法进入暂停阶段第二步。

设置Pause操作超时时间。

ActivityStack与当前将要暂停的Activity处于不同进程中,因此ActivityStack需要通过当前将要暂停的Activity的ProcessRecord信息得到ApplicationThreadProxy,进而通过该代理对象访问主线程定义的ApplicationThread,最终通过ApplicationThread暂停Activity。通知Activity暂停时,ActivityStack需要向自身消息队列发送一个PAUSE_TIMEOUT_MSG消息,并且指定该消息在PAUSE_TIMEOUT(500)ms后处理,因此当暂停操作无法在500ms内完成时,ActivityStack便处理Pause超时。

2.schedulePauseActivity

进入ApplicationThreadProxy的schedulePauseActivity方法,该方法通过Binder通信进而调用其服务端ActivityThread$ApplicationThread的同名方法,代码如下:


public final class ActivityThread{

……

final H mH=new H();

……

private class ApplicationThread extends ApplicationThreadNative{

……

public final void schedulePauseActivity(IBinder token, boolean finished,

boolean userLeaving, int configChanges){

queueOrSendMessage(//本例为PAUSE_ACTIVITY

finished?H.PAUSE_ACTIVITY_FINISHING:H.PAUSE_ACTIVITY,

token,//本例为Launcher

(userLeaving?1:0),//true

configChanges);

}

……


queueOrSendMessage通过ActivityThread的成员变量mH向主线程消息队列发送PAUSE_ACTIVITY消息,处理该消息的便是H.handleMessage方法,代码如下:


private class H extends Handler{

public void handleMessage(Message msg){

switch(msg.what){

……

case PAUSE_ACTIVITY:

handlePauseActivity((IBinder)msg.obj, false, msg.arg1!=0,msg.arg2);

maybeSnapshot();//记录系统运行快照(Snap Shot),需要开启Profile

break;

……


H. handleMessage方法根据消息类型匹配到switch代码块的PAUSE_ACTIVITY分支,进而调用handlePauseActivity处理PAUSE_ACTIVITY消息,此时进入暂停阶段的第三步操作。

3.handlePauseActivity

暂停阶段的第三步操作由ActivityThead.handlePauseActivity方法完成,代码如下:


private void handlePauseActivity(IBinder token, boolean finished,

boolean userLeaving, int configChanges){

/*token表示Launcher的BinderProxy, r便是

ActivityRecord对应的ActivityClientRecord/

ActivityClientRecord r=mActivities.get(token);

if(r!=null){

if(userLeaving){//true

performUserLeavingActivity(r);

}

r.activity.mConfigChangeFlags|=configChanges;

performPauseActivity(token, finished, r.isPreHoneycomb());

if(r.isPreHoneycomb()){//判断SDK版本是否是HONEYCOMB之前的版本

//等待要暂停的应用进程的异步操作完成,保持数据完整

QueuedWork.waitToFinish();

}

//通知ActivityManagerService,已经暂停完毕

try{

ActivityManagerNative.getDefault().activityPaused(token);

}catch(RemoteException ex){

}

}

}


本例的userLeaving为true,因此需要首先执行performUserLeavingActivity方法,代码如下:


final void performUserLeavingActivity(ActivityClientRecord r){

//在本例中,r代表Launcher

mInstrumentation.callActivityOnUserLeaving(r.activity);

}


performUserLeavingActivity调用了Instrumentation.callActivityOnUserLeaving方法,代码如下:


public void callActivityOnUserLeaving(Activity activity){

activity.performUserLeaving();

}

final void performUserLeaving(){

onUserInteraction();

onUserLeaveHint();

}


Instrumentation. callActivityOnUserLeaving方法调用Activity生命周期的onUserInteraction和onUserLeaveHint方法,因此这两个方法都是在Activity.onPause方法之前被调用。

执行完performUserLeavingActivity方法后,接着调用performPauseActivity方法进入暂停阶段的第四步操作,最后调用activityPaused进入暂停阶段的第五步操作。

4.performPauseActivity

暂停阶段的第四步操作由ActivityThead.performPauseActivity完成,该方法有两个重载方法,performPauseActivity(IBinder token,……)和performPauseActivity(ActivityClientRecord r,……)。这里首先调用的是第一个重载方法,代码如下:


final Bundle performPauseActivity(IBinder token, boolean finished, boolean saveState){

ActivityClientRecord r=mActivities.get(token);

return r!=null?performPauseActivity(r, finished, saveState):null;

}


performPauseActivity方法首先从ActivityThread.mActivities获取token对应的ActivityClientRecord,然后调用重载方法performPauseActivity(ActivityClientRecord r,……)执行后续操作。token表示当前要暂停的Activity在ActivityManagerService中对应的ActivityRecord,而ActivityClientRecord则是该Activity在ActivityThread中的存储形式。

接下来分析第二个重载方法,代码如下:


final HashMap<Activity, ArrayList<OnActivityPausedListener>>

mOnPauseListeners

=new HashMap<Activity, ArrayList<OnActivityPausedListener>>();

……

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,

boolean saveState){

if(r.paused){

if(r.activity.mFinished){//已经是finish状态,不需要暂停了

return null;

}

……

}

Bundle state=null;

if(finished){

r.activity.mFinished=true;

}

try{

if(!r.activity.mFinished&&saveState){//保存当前状态

state=new Bundle();

state.setAllowFds(false);

mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);

r.state=state;

}

r.activity.mCalled=false;

mInstrumentation.callActivityOnPause(r.activity);//暂停

if(!r.activity.mCalled){

throw new SuperNotCalledException(

"Activity"+r.intent.getComponent().toShortString()+

"did not call through to super.onPause()");

}

}

……

r.paused=true;

//通知OnActivityPausedListener执行其监听操作

ArrayList<OnActivityPausedListener>listeners;

synchronized(mOnPauseListeners){

listeners=mOnPauseListeners.remove(r.activity);

}

int size=(listeners!=null?listeners.size():0);

for(int i=0;i<size;i++){

listeners.get(i).onPaused(r.activity);//执行Pause监听器的回调方法

}

return state;

}


performPauseActivity(ActivityClientRecord r,……)方法依次执行了callActivityOnSaveInstance State、callActivityOnPause、OnActivityPausedListener.onPaused方法。

1)callActivityOnSaveInstanceState的代码如下:


public void callActivityOnSaveInstanceState(Activity activity, Bundle outState){

activity.performSaveInstanceState(outState);

}

接下来分析performSaveInstanceState方法,代码如下:

final void performSaveInstanceState(Bundle outState){

//Activity生命周期的onSaveInstanceState方法

onSaveInstanceState(outState);

saveManagedDialogs(outState);//保存Activity的ManagedDialog

}


callActivityOnSaveInstanceState调用Activity生命周期的onSaveInstanceState方法,并保存其ManagedDialog。

2)callActivityOnPause的代码如下:


public void callActivityOnPause(Activity activity){

activity.performPause();

}


接下来分析Activity的performPause方法,代码如下:


final void performPause(){

mFragments.dispatchPause();//改变Fragment的状态

mCalled=false;

onPause();//调用Activity生命周期的onPausue方法

mResumed=false;//此时已是非resumed状态

if(!mCalled&&getApplicationInfo().targetSdkVersion>=

android.os.Build.VERSION_CODES.GINGERBREAD){

throw new SuperNotCalledException(

"Activity"+mComponent.toShortString()+

"did not call through to super.onPause()");

}

mResumed=false;

}


callActivityOnPause最终调用了Activity生命周期的onPause方法。

3)ActivityThread的成员变量mOnPauseListeners存储了监听Activity.onPause的监听器(OnActivityPausedListener),可以通过ActivityThread.registerOnActivityPausedListener方法注册监听器,并在OnActivityPausedListener.onPause方法中实现具体的处理操作。

以上操作完成后,Activity真正执行了onPause操作,进入暂停状态,此后执行暂停阶段的第五个步骤。

5.activityPaused

执行了Activity生命周期的onPause方法后,并不表示启动应用程序Activity的暂停阶段已经结束,此时还需要通知ActivityManagerService和ActivityStack,当前Activity已经进入暂停状态。暂停阶段的第五步由ActivityManagerProxy.activityPaused方法完成,该方法通过Binder通信进而调用ActivityManagerService.activityPaused方法完成操作,代码如下:


public final void activityPaused(IBinder token){

final long origId=Binder.clearCallingIdentity();

mMainStack.activityPaused(token, false);//调用ActivityStack的方法

Binder.restoreCallingIdentity(origId);

}


在本例中,token表示Launcher的ActivityRecord。接下来分析ActivityStack.activityPaused,代码如下:


final void activityPaused(IBinder token, boolean timeout){

ActivityRecord r=null;

synchronized(mService){

int index=indexOfTokenLocked(token);

if(index>=0){

r=mHistory.get(index);

//Pause操作已经处理,移除之前添加的超时消息

mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);

if(mPausingActivity==r){

r.state=ActivityState.PAUSED;//切换Activity状态为PAUSED

completePauseLocked();

}else{

……//Pause失败,记录到events log

}

}

}

}


ActivityManagerService接收到应用程序主线程已经进入暂停状态的通知后,从mHistory成员变量中找到该Activity,将其状态更新为PAUSED,然后调用completePauseLocked方法进入暂停阶段的第六步操作。

6.completePauseLocked

暂停阶段的第六步操作由completePauseLocked方法完成,代码如下:


private final void completePauseLocked(){

ActivityRecord prev=mPausingActivity;

if(prev!=null){//本例为Launcher

//如果被暂停的Activity处于finishing状态,则destroy

if(prev.finishing){//本例中Launcher运行于后台,不满足该分支

prev=finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);

}else if(prev.app!=null){

//如果需要等待新启动Activity可见,waitingVisible为true

if(prev.waitingVisible){

prev.waitingVisible=false;

mWaitingVisibleActivities.remove(prev);

}

//因为配置改变导致的暂停,需要destroy该Activity,随后重启它

if(prev.configDestroy){

destroyActivityLocked(prev, true, false,"pause-config");

}else{

//加入待stop列表,等待被stop

mStoppingActivities.add(prev);

//stop列表中Activity数大于3时,发送并处理IDLE_NOW_MSG消息

if(mStoppingActivities.size()>3){

scheduleIdleLocked();//最终由activeIdleInternal处理

}else{

checkReadyForSleepLocked();

}

}

}else{

prev=null;

}

mPausingActivity=null;//已经处理Pause操作,重置mPausingActivity

}

//非休眠或者准备关机状态时,再次调用resumeTopActivityLocked

if(!mService.isSleeping()){

resumeTopActivityLocked(prev);//本例中prev仍然是Launcher

}else{

checkReadyForSleepLocked();

if(topRunningActivityLocked(null)==null){

resumeTopActivityLocked(null);

}

}

if(prev!=null){//恢复接收WindowManagerService的Key Dispatch事件

prev.resumeKeyDispatchingLocked();

}

……

}


completePauseLocked方法首先针对当前已暂停的Activity进行后续处理,要么执行destroy操作,要么存入等待stop列表。然后再次调用resumeTopActivityLocked方法,本例中传入的参数prev仍然是Launcher。这里暂不分析Activity的destroy操作。本次调用resumeTopActivityLocked方法标志启动应用程序Activity的暂停阶段结束。