Android进阶知识(二十七):Activity的启动过程
Activity组件的主要作用是展示一个界面并和用户交互,其扮演的是一个前台界面的角色。关于Activity启动的触发(Intent)以及相关的启动模式等,笔者在Android基础知识(五):Activity的生命周期、Android基础知识(六):Activity的启动模式、Android基础知识(七):Activity互调之间的生命周期变化与onNewIntent()触发机制以及Android进阶知识(二):Activity启动模式进阶之多任务栈与Flags中做了介绍。
这一篇笔者将对Activity的启动过程的流程进行总结,并提及一些需要注意的点,这里笔者不会铺太多源码(毕竟太多了)。
一、ActivityTaskManagerService(ATMS)
Google将Android的版本更新到10.0版本(SDK 29)之后,Activity的启动流程相比之前发生了些许变化,其中最大的变化就是用来管理Activity的ActivityManagerService(AMS),变更为ActivityTaskManagerService(ATMS)。
为了兼容,原本的AMS代码也都委托给ATMS中进行处理。
public int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return mActivityTaskManager.startActivity(caller, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
}
这就严重导致了基于Android 5.0版本的《Android开发艺术探索》内的启动流程不适用,不过也无需担心,即使流程变动,其基本思想是不会改变的。
二、Activity的启动过程
Activity的启动过程流程图如下所示。
其中黑色虚线是指过程经过多个重载方法,最终调用箭头指向的方法。紫色虚线指该过程调用为远程服务调用,即IPC过程。
上面的流程图是方法具体调用的流程(其实也是忽略了许多重载方法调用),简单起见,Activity启动过程的流程可以用如下表示。
三、ApplicationThread
ApplicationThread是ActivityThread的内部类,继承自IApplicationThread.Stub即Binder。
private class ApplicationThread extends IApplicationThread.Stub {
// ...
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
// ...
}
因此在Activity启动流程中,ATMS回调ApplicationThread的方法,该方法在Binder线程池中的线程执行,这也是为什么需要使用Handler来切换线程到ActivityThread所在线程的原因。
四、onPause与onResume的执行时机
在流程中,我们可以知道Activity的启动过程在ActivityStack的resumeTopActivityInnerLocked方法中,其会调用startPausingLocked方法,从而回调ApplicationThread,接着线程切换调用ActivityThread的handlePauseActivity方法,以执行回调onPause。
这也就是在基础知识阶段中,提到的在启动新Activity时候,旧的Activity的onPause方法回调在新Activity的onCreate方法回调之前执行的原因。
那么另一个问题来了,Activity的启动过程是开发者通过代码触发的,同理通过调用finish方法也可以触发Activity的结束过程(流程基本类似),那么其他方法像onResume是如何被调用的呢?
在《Android开发艺术探索》以及很多博客上说的是,ActivityThread的handleLaunchActivity中调用了handleResumeActivity,从而调用了onResume。但是事实上,在Android 10.0的源码完全不是怎么一回事。这导致了笔者大脑当机了半天。
那么到底是怎么调用的呢?笔者通过阅读源码,终于找到了源头。在realStartActivityLocked中有这样一段代码。
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// ...
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
// ...
}
根据上面的流程我们知道clientTransaction最终会被TransactionExecutor的execute使用,而这里调用的clientTransaction.setLifecyclesStateRequest表示设置客户端,即Application在执行事务后应该处于的生命周期状态。由于是启动Activity,因此这里的lifecycleItem为ResumeActivityItem,也就是Application应该处于resume状态。
再来看看execute的部分代码,在上面的流程中execute调用了executeCallbacks方法之外,还调用了另一个方法executeLifecycleState。
public void execute(ClientTransaction transaction) {
// ...
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
// ...
// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
我想读者也明白了executeLifecycleState就是取出前面设置了lifecycleItem进而调用对应的execute方法,最终就可以回调到onResume。这里总结一些流程如下,这里省略了部分流程以及executeCallback的流程。
值得一提的是,与onCreate的调用不同,performResumeActivity是调用的Activity的performResume方法,接着调用Instrumentation的callActivityOnResume,进而调用Activity的onResume方法。
五、performLaunchActivity的工作
在前面的流程中,笔者只是把performLaunchActivity最重要的工作调用Instrumentation的callActivityOnCreate方法,从而调用onCreate方法,画入了流程中,但是实际上performLaunchActivity的工作主要有五件事。
- 从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);
}
- 通过Instrumentation的newActivity方法使用类加载器创建Activity对象
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.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);
}
}
- 通过LoadedApk的makeApplication方法尝试创建Application对象
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
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")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
// ...
return app;
}
从makeApplication的实现可以看出,如果Application已经被创建,那么不会再重复创建,这也就意味着一个应用只有一个Application对象。
另外Application创建完毕之后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate方法。
- 创建ContextImpl对象并通过Activity的attach方法完成重要数据初始化
ContextImpl appContext = createBaseContextForActivity(r);
// ...
Configuration config = new Configuration(mCompatConfiguration);
// ...
appContext.setOuterContext(activity);
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, window, r.configCallback,
r.assistToken);
ContextImpl是一个很重要的数据结构,它是Context的具体实现。ContextImpl通过Activity的attach方法和Activity建立关联,除此之外attach中Activity还完成Window的创建并建立自己和Window的关联,这样Window接收到的外部输入事件后就可以将事件传递给Activity(具体见笔者笔记:Android进阶知识(二十一):Window的创建过程)。
- 调用Activity的onCreate方法
这个在流程中已经有所体现,其调用Instrumentation的callActivityOnCreate方法,进而调用Activity的onCreate,至此Activity的启动过程就完成了。
参考资料:《Android艺术开发探索》
在Android 10.0中Activity的启动流程