Activity启动流程 (Android13)
本文以时序图的形式来展示activity的启动过程,相比于贴源码会更加直观。本文的讲解的流程是基于MainActivity
使用standard模式启动SecondActivity
,且两个Activity都在同一个应用中,最后的部分也会讲解一下进程的启动。
第一阶段:执行startActivity
zenuml group App { <<App>> act as Activity <<App>> ins as Instrumentation } group AMS { <<AMS>> atms as ActivityTaskManagerService #F0F8FF ActivityStarter #F0F8FF } act.startActivity { act.startActivityForResult { ins.execStartActivity { atms.startActivity { atms.startActivityAsUser { //没有缓存则创建 new ActivityStarter() ActivityStarter."① execute" } } } } }
zenuml <<AMS>> ActivityStarter #F0F8FF ActivityStarter."① execute" { executeRequest { new ActivityRecord() startActivityUnchecked { startActivityInner { Task.addChild Task.startActivityLocked RootWindowContainer.resumeFocusedTasksTopActivities { Task.resumeTopActivityUncheckedLocked { resumeTopActivityInnerLocked { TaskFragment.resumeTopActivity { //pause当前activity "② startPausing()" if (! isProcessRunning) { ActivityTaskManagerService.startProcessAsync } } } } } } handleStartResult postStartActivityProcessing } } }
第二阶段:pause当前activity
启动SecondActivity
之前会先执行MainActivity
的pause操作:
在Android 9之前的版本,ActivityThread
中通过LAUNCH_ACTIVITY
消息来启动activity,源码如下:
1 | //android\app\ActivityThread.java |
但从Andorid 9开始,ActivityThread
去掉了LAUNCH_ACTIVITY
PAUSE_ACTIVITY
RESUME_ACTIVITY
等消息,而是改成了EXECUTE_TRANSACTION,通过ClientTransaction这套机制来执行activity生命周期流程,相关源码如下:
1 | public void handleMessage(Message msg) { |
下面是ClientTransaction
类图:
第三阶段:启动新Activity
下面继续Activity启动流程:
执行SecondAcitivity
的启动流程:
第四阶段:View添加到Window
下面这个时序图是对上面时序图的进一步细化,① ② ③ ④与上面的序号一对一对应。
zenuml group { <<App>> ActivityThread <<App>> SecondActivity PhoneWindow DecorView <<App>> WindowManagerGlobal ViewRootImpl } SecondActivity."① attach" { attachBaseContext new PhoneWindow() PhoneWindow.setWindowManager } SecondActivity."② onCreate()" { setContentView { PhoneWindow.installDecor { new DecorView() mContentParent = generateLayout() "mContentParent.addView" } } } SecondActivity."③ onStart()" ActivityThread.handleResumeActivity { SecondActivity."④ onResume()" DecorView.setVisibility(INVISIBLE) WindowManagerGlobal.addView(DecorView) { new ViewRootImpl() "mViews.add(DecorView)" "mRoots.add(ViewRootImpl)" ViewRootImpl.setView(DecorView) } SecondActivity.makeVisible { DecorView.setVisibility(VISIBLE) { ViewRootImpl.invalidateChild { invalidate { scheduleTraversals } } } } }
Activity.onCreate()中通过调用setContentView
来触发DecorView的创建,DecorView就是rootView(View#getRootView
)。通过Hierarchy Viewer看下DecorView结构:
用户自定义的View会被添加到PhoneWindow.mContentParent中,而mContentParent是DecorView的一个子孙View。Activity.onResume()之后就会就会把DecorView添加到WindowManagerGlobal中,对生成对应的ViewRootImpl。ViewRootImpl就是DecorView的parent。
最后阶段就会执行UI的渲染,对应ViewRootImpl.scheduleTraversals
。
下面是Activity、Task之间的类图关系:
启动新APP进程
如果需要启动的activity不在同一个app中,就需要启动新的进程。
zenuml ActivityTaskManagerService.startProcessAsync { H.sendMessage { ActivityManagerService.startProcess { startProcessLocked { ProcessList.startProcessLocked { newProcessRecordLocked { new ProcessRecord() } //with ProcessRecord startProcessLocked { ProcessList."配置runtimeFlags" //异步启动线程 ProcessList -> ActivityManagerService : mProcStartHandler.post } } } } } }
zenuml ActivityManagerService."mProcStartHandler.dispatchMessage" { ProcessList.handleProcessStart { startProcess { ProcessStartResult = Process.start { ProcessStartResult = ZygoteProcess.start { startViaZygote { ZygoteProcess."组装参数列表args" zygoteSendArgsAndGetResult { //通过LocalSocket向zygote发送进程启动参数 //并阻塞读取进程pid attemptZygoteSendArgsAndGetResult } } } } } handleProcessStartedLocked { ActivityManagerService.addPidLocked { ActivityTaskManagerService."onProcessMapped(pid, WindowProcessController)" { ActivityTaskManagerService."mProcessMap.put(pid, proc)" } } } } }
1 | //android-13.0.0_r41\frameworks\base\core\java\android\os\ZygoteProcess.java |
新的app进程启动运行的入口是ActivityThread.main
函数:
1 | public static void main(String[] args) { |
zenuml group App { ApplicationThread Application ActivityThread mH } group AMS { ActivityManagerService } ActivityThread.attach { ActivityManagerService.attachApplication { Binder.getCallingPid attachApplicationLocked { "根据pid获取ProcessRecord" ApplicationThread.bindApplication { mH.sendMessage(BIND_APPLICATION) } } } } ActivityThread.handleMessage(BIND_APPLICATION) { handleBindApplication { new Application() Application.attachBaseContext() Application.onCreate() } }