Activity组件的主要作用是展示一个界面并和用户交互,它扮演的是一种前台界面的角色,在显示调用的情形下,只需要通过如下代码即可完成。
Intent intent=new Intent(this,TestActivity.class);
startActivity(intent);
通过上面代码即可启动一个具体的Activity,然后这个Activity就会被系统启动并展示在用户的眼前,但是系统内部是如何启动一个Activity的呢?比如新Activity的对象是何时创建的,onCreate方法又是在何时回调的等等,本文将针对这些问题对Activity的整体流程进行讲解。
我们从Activity的startActivity方法开始分析,startActivity的方法有好几种重载方式,它们最终会调用startActivityForResult,它的实现如下所示。
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
...ignore some code...
} else {
if (options != null) {
//当现在的Activity有父Activity的时候会调用,但是在startActivityFromChild()内部实际还是调用的mInstrumentation.execStartActivity()
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
...ignore some code...
}
上面代码我们只关注mParent=null这部分逻辑就行,需注意mMainThread.getApplicationThread()这个参数,它的类型是ApplicationThread,ApplicationThread是ActivityThread的一个内部类,ApplicationThread和ActivityThread在Activity的启动过程中发挥着很重要的作用。接着看Instrumentation的execStartActivity方法,代码如下。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...ignore some code...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
从上面代码可以看出,启动Activity真正的实现由ActivityManagerNative.getDefault()的startActivity方法来完成,
这里的ActivityManagerNative.getDefault返回的就是ActivityManagerService的远程接口,即ActivityManagerProxy。
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
//从类声明上,我们可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
static public IActivityManager getDefault() {
return gDefault.get();
}
//通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得
private static final Singleton gDefault = new Singleton() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
//最终返回的还是一个ActivityManagerProxy对象
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
//这里面的Binder类型的obj参数会作为ActivityManagerProxy的成员变量保存为mRemote成员变量,负责进行IPC通信
return new ActivityManagerProxy(obj);
}
}
再看ActivityManagerProxy.startActivity(),在这里面做的事情就是IPC通信,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向AMS发送数据进行通信。
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
ActivityManagerProxy只是通过这种方式对要传输给服务器的数据进行打包,真正实现的是ActivityManagerService。
但是这个地方并不是直接由客户端传递给服务器,而是通过Binder驱动进行中转。Binder驱动原理暂时忽略,我们把他当做一个中转站就OK,客户端调用ActivityManagerProxy接口里面的方法,把数据传送给Binder驱动,然后Binder驱动就会把这些东西转发给服务器的ActivityManagerServices,由ActivityManagerServices去真正的实施具体的操作。
客户端:ActivityManagerProxy =====>Binder驱动=====> ActivityManagerService:服务端
从上面的分析看,,ActivityManagerNative.getDefault()实际上是AMS,因此Activity的启动过程转移到了AMS中,接着我们分析AMS的startActivity方法。
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
...ignore some code...
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
可以看出,Activity的启动过程又转移到了ActivityStackSupervisor的startActivityMayWait方法中了,在startActivityMayWait中又调用了startActivityLocked方法,然后startActivityLocked方法又调用了startActivityUncheckedLocked(),此时要启动的Activity已经通过检验,被认为是一个正当的启动请求。终于,在这里调用到了ActivityStack的startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options)。
ActivityRecord代表的就是要开启的Activity对象,里面分装了很多信息,比如所在的ActivityTask等,如果这是首次打开应用,那么这个Activity会被放到ActivityTask的栈顶。
ActivityStack.startActivityLocked()方法如下:
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
//ActivityRecord中存储的TaskRecord信息
TaskRecord rTask = r.task;
...ignore some code...
//如果不是在新的ActivityTask(也就是TaskRecord)中的话,就找出要运行在的TaskRecord对象
TaskRecord task = null;
if (!newTask) {
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
// task中的所有Activity都结束了
continue;
}
if (task == r.task) {
// 找到了
if (!startIt) {
task.addActivityToTop(r);
r.putInHistory();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}
...ignore some code...
// Place a new activity at top of stack, so it is next to interact
// with the user.
task = r.task;
task.addActivityToTop(r);
task.setFrontOfTask();
...ignore some code...
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}
从ActivityStackSupervisor到ActivityStack,又调回ActivityStackSupervisor, 看下StackSupervisor.resumeTopActivitiesLocked(this, r, options)
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = getFocusedStack();
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
...ignore some code...
return result;
}
又调回ActivityStack的resumeTopActivityLocked()方法
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
inResumeTopActivity = false;
}
return result;
}
然后调用ActivityStack的resumeTopActivityInnerLocked(prev, options)方法,resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisor的startSpecificActivityLocked方法,源码如下:
startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
从上面代码可以看出startSpecificActivityLocked 方法调用了realStartActivityLocked,为了更清晰地说明Activity的启动过程在ActivityStackSupervisor和ActivityStack之间传递顺序,下面给出一张图。
在ActivityStackSupervisor的realStartActivityLocked方法中有如下一段代码:
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
r.icicle, r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
app.thread. scheduleLaunchActivity,实际是调用ApplicationThreadProxy.scheduleLaunchActivity()方法,ApplicationThreadProxy是ApplicationThreadNative的内部类
客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务端
这里和上面的逻辑一样。ApplicationThreadProxy把数据封装好,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向发送ApplicationThread数据,绕了一大圈,Activity的启动过程最终回到了ApplicationThread,ApplicationThread通过scheduleLaunchActivity启动Activity,代码如下所示
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List pendingResults,
List pendingNewIntents, boolean notResumed, boolean isForward,
ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
在ApplicationThread中,scheduleLaunchActivity实现很简单,就是发送一个启动的消息(H.LAUNCH_ACTIVITY)交给Handler处理,这个Handler就叫H,接着看一下Handler对消息的处理
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
//ignore some code
public vhandleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
//ignore some code
}
从 case LAUNCH_ACTIVITY这可以知道,Activity的启动过程由ActivityThread的handleLaunchActivity实现,源码如下:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//ignore some code
Activity a = performLaunchActivity(r, customIntent);
...
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
...
从上面源码看出,performLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过handleResumeActivity方法来调用被启动Activity的onResume方法,performLaunchActivity这个方法主要完成了如下几件事
1.从ActivityClientRecord中获取待启动的Activity的组件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
2.通过Instrumentation的newActivity方法使用类加载器创建Activity对象
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
Instrumentation的newActivity方法,实现比较简单,就是通过类加载器来创建Activity对象:
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
3.通过LoadApk的makeApplication方法创建Application对象
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
...ignore some code...
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
...ignore some code...
从makeApplication的实现可以看出,如果Application创建过了,就不会再创建,这也意味着一个应用只有一个Application对象,Application对象也是通过Instrumentation(newApplication)完成的,和newActivity一样,都是通过类加载器实现。Application创建后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate方法。
4.创建Context对象并通过Activity的attach方法完成一些重要数据的初始化
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
Context是通过Activity的attach方法和Activity关联的,除此之后,在attach中Activity还会完成Window的创建并建立关联,这样当Window接到外部输入事件后就可以将事件传递给Activity。
5.调用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state),由于Activity的onCreate已经被调用,这也意味着Activity已经完成了整个启动过程。
参考文章
【凯子哥带你学Framework】Activity启动过程全解析