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的暂停阶段结束。