11.2.5 显示Activity

启动应用程序Activity的第五个阶段的主要功能是显示Activity,其入口点是ActivityStack.realStartActivityLocked方法,该方法在attachApplicationLocked执行完bindApplication方法后开始执行,其主要功能是加载Activity,并执行其生命周期的onCreate、onStart、onResume等方法,最终显示Activity。

1.ActivityStack.realStartActivityLocked

Activity显示阶段的第一步是ActivityStack.realStartActivityLocked,代码如下:


final boolean realStartActivityLocked(ActivityRecord r,

ProcessRecord app, boolean andResume, boolean checkConfig)

throws RemoteException{

/*当Activity attach到Application,并且应用进程没有异常状态(crash, ANR)

时,需要通过WindowManagerService冻结屏幕并设置Activity可见/

r.startFreezingScreenLocked(app,0);

mService.mWindowManager.setAppVisibility(r.appToken, true);

……

//在ActivityRecord中记录ProcessRecord,即Activity需要保存其运行进程的信息

r.app=app;

app.waitingToKill=null;

//在ProcessRecord中记录ActivityRecord,一个进程可以运行多个Activity

int idx=app.activities.indexOf(r);

if(idx<0){

app.activities.add(r);

}

mService.updateLruProcessLocked(app, true, true);//更新LRU

try{

//此时已经创建应用程序主线程,这里不为null

if(app.thread==null){

throw new RemoteException();

}

List<ResultInfo>results=null;

List<Intent>newIntents=null;

if(andResume){//本例为true

results=r.results;

newIntents=r.newIntents;

}

if(r.isHomeActivity){//本例为false

mService.mHomeProcess=app;

}

r.sleeping=false;

……

//app.thread即ApplicationThreadProxy,是一个BinderProxy对象

//Launch Activity主要包括onCreate、onStart和onResume

app.thread.scheduleLaunchActivity(new Intent(r.intent),

r.appToken, System.identityHashCode(r),r.info,

new Configuration(mService.mConfiguration),

r.compat, r.icicle, results, newIntents,!andResume,

mService.isNextTransitionForward(),profileFile,

profileFd, profileAutoStop);

……

}catch(RemoteException e){

}

r.launchFailed=false;

……

if(andResume){//true

r.state=ActivityState.RESUMED;

r.stopped=false;

mResumedActivity=r;

r.task.touchActiveTime();

if(mMainStack){

//添加到最近Task列表,默认最大数量为20个

mService.addRecentTaskLocked(r.task);

}

completeResumeLocked(r);//执行onResume后的处理

checkReadyForSleepLocked();

r.icicle=null;

r.haveState=false;

}else{

r.state=ActivityState.STOPPED;

r.stopped=true;

}

if(mMainStack){//系统升级时或第一次启动时需要运行Setup Wizard

mService.startSetupActivityLocked();

}

return true;

}


在启动应用程序Activity过程中,ActivityStack.realStartActivityLocked的主要工作由两个方法完成:ApplicationThreadProxy.scheduleLaunchActivity和ActivityStack.completeResume Locked。其中scheduleLaunchActivity用于在ActivityManagerService所在进程向应用程序主线程的消息循环发送LAUNCH_ACTIVITY消息,进而在应用程序主线程中回调Activity生命周期的onCreate、onStart、onResume等方法显示Activity。onResume方法执行完毕后,需要首先将当前显示Activity所在的Task加入最近Task列表,然后调用completeResumeLocked在ActivityManagerService中进行后续处理。

2.ApplicationThread.scheduleLaunchActivity

显示Activity的第二步是ApplicationThreadProxy.scheduleLaunchActivity,通过Binder通信进而调用ApplicationThread.scheduleLaunchActivity方法,代码如下:


public final class ActivityThread{

……

private class ApplicationThread extends ApplicationThreadNative{

……

public final void scheduleLaunchActivity(……){

//创建应用程序进程中保存的Activity信息,以ActivityClientRecord表示

ActivityClientRecord r=new ActivityClientRecord();

//对应于ActivityManagerService中保存的ActivityRecord的BinderProxy

r.token=token;

r.ident=ident;

r.intent=intent;

r.activityInfo=info;

……

//向应用程序主线程发送LAUNCH_ACTIVITY消息

queueOrSendMessage(H.LAUNCH_ACTIVITY, r);

}


ApplicationThread. scheduleLaunchActivity首先在应用程序进程中创建ActivityClientRecord,其对应于ActivityManagerService中的ActivityRecord;然后通过queueOrSendMessage方法向应用程序主线程ActivityThread发送LAUNCH_ACTIVITY消息。消息的处理由定义在ActivityThread.H的handleMessage方法完成,代码如下:


public final class ActivityThread{

……

final H mH=new H();

……

private class H extends Handler{

public void handleMessage(Message msg){

switch(msg.what){

case LAUNCH_ACTIVITY:{

ActivityClientRecord r=(ActivityClientRecord)msg.obj;

//获取应用程序Activity的LoadedApk

r.packageInfo=getPackageInfoNoCheck(

r.activityInfo.applicationInfo, r.compatInfo);

handleLaunchActivity(r, null);

}break;

}

}


应用程序主线程收到LAUNCH_ACTIVITY消息后,会在其消息处理器mH的handleMessage方法中根据消息类型匹配switch代码块的LAUNCH_ACTIVITY分支,在该分支中,首先需要根据要启动的Activity信息,找到其对应的APK文件信息(LoadedApk),然后调用handleLaunchActivity进一步处理Activity的启动过程。

以上处理过程的主要流程如图11-4所示。

11.2.5 显示Activity - 图1

图 11-4 scheduleLaunchActivity方法执行流程

3.ActivityThread.handleLaunchActivity

显示Activity的第三步是ActivityThread.handleLaunchActivity,代码如下:


private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent){

unscheduleGcIdler();//暂停调度Idler状态的GC消息处理,见第7章

……

//本例为com.android.settings.Settings

Activity a=performLaunchActivity(r, customIntent);

if(a!=null){

……

handleResumeActivity(r.token, false, r.isForward);

if(!r.activity.mFinished&&r.startsNotResumed){

……

}

}else{

try{//Activity启动失败,直接销毁

ActivityManagerNative.getDefault().

finishActivity(r.token, Activity.RESULT_CANCELED, null);

}catch(RemoteException ex){

//Ignore

}

}

}


handleLaunchActivity将启动Activity的过程分为Launch阶段和Resume阶段,这两个阶段分别由performLaunchActivity和handleResumeActivity完成,如果Activity启动失败,则需要调用finishActivity予以销毁。

4.ActivityThread.performLaunchActivity

显示Activity的第四步是ActivityThread.performLaunchActivity,代码如下:


private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){

ActivityInfo aInfo=r.activityInfo;//获取Activity信息

……

ComponentName component=r.intent.getComponent();

……

Activity activity=null;

try{

java.lang.ClassLoader cl=r.packageInfo.getClassLoader();

/通过Java反射机制加载并创建Activity对象,本例中创建com.android.settings.Settings/

activity=mInstrumentation.newActivity(

cl, component.getClassName(),r.intent);

……

}catch(Exception e){

}

try{

/*app中存储要启动的应用程序包名、Activity名、APK文件名等信息,本例

*中主要包含以下信息com.android.settings/com.android.settings

Settingsdir=/system/app/Settings.apk/

Application app=r.packageInfo.makeApplication(false, mInstrumentation);

if(activity!=null){

//创建并初始化Activity对应的Context

ContextImpl appContext=new ContextImpl();

appContext.init(r.packageInfo, r.token, this);

appContext.setOuterContext(activity);

……

//将其他应用程序信息附加(attach)到Activity

activity.attach(appContext, this, getInstrumentation(),r.token,

r.ident, app, r.intent, r.activityInfo, title, r.parent,

r.embeddedID, r.lastNonConfigurationInstances, config);

……

activity.mCalled=false;

//回调onCreate方法

mInstrumentation.callActivityOnCreate(activity, r.state);

……

r.activity=activity;

r.stopped=true;

if(!r.activity.mFinished){

activity.performStart();//回调onStart方法

r.stopped=false;

}

if(!r.activity.mFinished){

if(r.state!=null){//本例为false

//回调onRestoreInstanceState方法

mInstrumentation.callActivityOnRestoreInstanceState(

activity, r.state);

}

}

if(!r.activity.mFinished){

activity.mCalled=false;

mInstrumentation.callActivityOnPostCreate(activity, r.state);

//回调onPostCreate方法

……

}

}

r.paused=true;

/*在应用程序主线程中记录当前Activity, r.token是ActivityManagerService

中存储的ActivityRecord的BinderProxy/

mActivities.put(r.token, r);

}

……

return activity;

}


performLaunchActivity方法的主要工作是:首先创建Activity对应的Application和Context,并将Activity所需的其他信息附加(attach)到Activity上,然后通过Instrumentation回调Activity生命周期的方法,这些方法包括onCreate、onStart、onRestoreInstanceState(本例未回调该方法)和onPostCreate。通常,应用程序Activity在onCreate中通过setContentView方法设置UI布局和控件,此时Activity便可以显示UI了。

Instrumentation回调Activity生命周期的过程很简单,这里不赘述。将Activity所需的其他信息附加到Activity上由Activity.attach方法完成,代码如下:


final void attach(Context context,……){

attachBaseContext(context);//Activity关联到Context

mFragments.attachActivity(this);//FragmentManager记录当前Activity

//创建Activity对应的Window,对于手机,这个窗口是PhoneWindow

mWindow=PolicyManager.makeNewWindow(this);

mWindow.setCallback(this);

mWindow.getLayoutInflater().setPrivateFactory(this);

……

mUiThread=Thread.currentThread();//当前线程视为UI线程

mMainThread=aThread;//当前ActivityThread视为主线程

mInstrumentation=instr;

mToken=token;//ActivityManagerService中ActivityRecord的BinderProxy

mIdent=ident;

mApplication=application;

mIntent=intent;

mComponent=intent.getComponent();

mActivityInfo=info;

mTitle=title;

mParent=parent;//本例parent为null

mEmbeddedID=id;

mLastNonConfigurationInstances=lastNonConfigurationInstances;

//窗口需要使用WindowManager

mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),

(info.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED)!=0);

if(mParent!=null){

mWindow.setContainer(mParent.getWindow());

}

mWindowManager=mWindow.getWindowManager();

mCurrentConfig=config;

}


可见,Activity通过attach方法将大量信息附加到自身,这些信息包括Context、Fragmen tManager、UI线程和主线程、PhoneWindow等,这样便构建了完整的Activity运行框架。

以上处理过程的主要流程如图11-5所示。

11.2.5 显示Activity - 图2

图 11-5 performLaunchActivity方法执行流程

performLaunchActivity方法执行完毕后,进入显示Activity的第五个主要步骤。

5.ActivityThread.handleResumeActivity

显示Activity的第五步由ActivityThread.handleResumeActivity方法完成,代码如下:


final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward){

unscheduleGcIdler();

//回调onResume方法

ActivityClientRecord r=performResumeActivity(token, clearHide);

if(r!=null){

final Activity a=r.activity;

……

/*此时mStartedActivity为false。如果该值为true,说明

上一个Activity还在执行onResume方法/

boolean willBeVisible=!a.mStartedActivity;

if(!willBeVisible){//本例为true,表示该Activity是否可见

try{

willBeVisible=ActivityManagerNative.getDefault()

.willActivityBeVisible(a.getActivityToken());

}catch(RemoteException e){

}

}

if(r.window==null&&!a.mFinished&&willBeVisible){

r.window=r.activity.getWindow();

View decor=r.window.getDecorView();//设置根View

decor.setVisibility(View.INVISIBLE);

ViewManager wm=a.getWindowManager();

WindowManager.LayoutParams l=r.window.getAttributes();

a.mDecor=decor;

l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

l.softInputMode|=forwardBit;

if(a.mVisibleFromClient){

a.mWindowAdded=true;

wm.addView(decor, l);

}

}else if(!willBeVisible){

//如果Activity在onResume时,启动了另一个Activity,此时窗口不可见

r.hideForNow=true;

}

if(!r.activity.mFinished&&willBeVisible

&&r.activity.mDecor!=null&&!r.hideForNow){

……

r.activity.mVisibleFromServer=true;

mNumVisibleActivities++;//当前屏幕可见Activity数,此时为1

if(r.activity.mVisibleFromClient){

r.activity.makeVisible();

}

}

if(!r.onlyLocalRequest){//满足该分支的条件

r.nextIdle=mNewActivities;

mNewActivities=r;

//onResume后进入Idle状态,此时将向主线程的消息队列注册IdleHandler

Looper.myQueue().addIdleHandler(new Idler());

}

r.onlyLocalRequest=false;

}else{

……//onResume时出现异常,直接destroy该Activity


ActivityThread. handleResumeActivity方法首先会回调Activity的onResume方法,然后设置Activity对应的View可见,最后向应用程序主线程的消息循环中添加一个Idle状态的处理器:Idler对象。

可见,当Activity执行完onResume方法后,会进入Idle状态。当应用程序主线程的消息队列中没有其他要处理的消息时,将处理Idle消息,进而调用Idler对象的queueIdle方法。相关内容请参考第7章。

6.ActivityThread.performResumeActivity

显示Activity的第六步是回调Activity的onResume方法,由ActivityThread.performResume Activity完成,代码如下:


public final ActivityClientRecord performResumeActivity(IBinder token,

boolean clearHide){

ActivityClientRecord r=mActivities.get(token);

if(r!=null&&!r.activity.mFinished){//本例为true

if(clearHide){//false

r.hideForNow=false;

r.activity.mStartedActivity=false;

}

try{

if(r.pendingIntents!=null){

//调用Activity生命周期的onNewIntent方法

deliverNewIntents(r, r.pendingIntents);

r.pendingIntents=null;

}

if(r.pendingResults!=null){

//调用Activity生命周期的onActivityResult方法

deliverResults(r, r.pendingResults);

r.pendingResults=null;

}

//调用Activity生命周期的onResume方法

r.activity.performResume();

r.paused=false;//此时真正进入非暂停状态

r.stopped=false;//此时真正进入非停止状态

r.state=null;

}

……

return r;

}


可见ActivityThread.performResumeActivity在回调Activity生命周期的onResume方法之前,还可能回调onNewIntent和onActivityResult方法。这里只分析如何回调onResume方法。

7.performResume

显示Activity的第七步是ActivityThread.performResumeActivity调用Activity的performResume方法,回调其生命周期的onResume方法,代码如下:


final void performResume(){

//如果当前Activity处于stop状态,依次调用Activity生命周期的onRestart和onStart方法

performRestart();

//执行Activity的Fragment的事务

mFragments.execPendingActions();

mLastNonConfigurationInstances=null;

mCalled=false;

//调用Activity生命周期的onResume方法

mInstrumentation.callActivityOnResume(this);

……

mFragments.dispatchResume();//Fragment切换到Resume状态

mFragments.execPendingActions();

//执行Activity生命周期的onPostResume方法

onPostResume();

……

}


可见onResume方法并非孤立执行的,如果当前Activity处于stop状态,需要首先回调其onRestart和onStart方法,然后再执行onResume方法,最后还需要执行onPostResume方法[1]

以上处理过程的主要流程如图11-6所示。

11.2.5 显示Activity - 图3

图 11-6 Activity的performResume方法执行流程

以上步骤执行完毕后返回ActivityStack.realStartActivityLocked方法,继续执行ActivityStack.completeResumeLocked方法。

8.ActivityStack.completeResumeLocked

显示Activity的第八步,当Activity执行完onResume方法返回ActivityManagerService进程后,需要调用ActivityStack.completeResumeLocked方法执行Activity.onResume的后续处理。代码如下:


private final void completeResumeLocked(ActivityRecord next){

next.idle=false;

next.results=null;

next.newIntents=null;

//Activity.onResume后会向应用程序主线程中添加Idle状态处理器

//ActivityManagerService通过IDLE_TIMEOUT_MSG消息监控其处理情况

Message msg=mHandler.obtainMessage(IDLE_TIMEOUT_MSG);

msg.obj=next;

mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);

if(mMainStack){

mService.reportResumedActivityLocked(next);

}

next.clearThumbnail();

if(mMainStack){

mService.setFocusedActivityLocked(next);//设置当前获取焦点的Activity

}

next.resumeKeyDispatchingLocked();

ensureActivitiesVisibleLocked(null,0);

mService.mWindowManager.executeAppTransition();

mNoAnimActivities.clear();

……

}


当Activity执行其onResume方法,并向应用程序主线程中加入Idle消息处理器后,ActivityStack向自身消息循环中发送IDLE_TIMEOUT_MSG消息,并指定该消息在10s后处理。接下来分析Activity Idle状态的处理过程。

[1]这里涉及Fragment运行,不在本书中讲解,读者可以参考Android官方开发者网站http://developer.android.com/reference/android/app/Fragment/html。