源码
要点
- mContentParent:下文中的mContentParent实际类型是ActionBarOverlayLayout,是我们布局文件的直接父布局
- Activity的展示过程大概就是atms回调activity的启动方法,然后会进行初始化PhoneWindow、DecorView。初始化完成后会等待wms回调onResume的逻辑处理,这里的重点是我们的UI展示关键类ViewRootImpl,它就是在这里处理的,最后onResume中会进行activity以下五个回调方法的处理:onNewIntent、onActivityResult、onRestart、onStart、onResume
setContentView流程
- Activity.setContentView
- PhoneWindow.setContentView
这里关键的方法就是installDecor方法
- 看看installDecor方法
这个方法没有太多的观赏性,因为就是单纯的初始化DecorView和mContentParent
PhoneWindow是在哪里初始化的
PhoneWindow是在Activity.attach方法中初始化的,代码如下:
ActivityThread.handleResumeActivity 处理Activity可见生命周期的理解
我们都知道Activity的生命周期是由atms控制的(低版本是ams),而ViewRootImpl是在onResume中初始化的,进步一onResume向上可以追溯到ActivityThread.handleResumeActivity方法。atms的跨进程调用就是会调用到ActivityThread.handleResumeActivity方法。因此我们的代码就是从ActivityThread.handleResumeActivity方法开始查看。
- ActivityThread.handleResumeActivity
如果不是第一次resumeactivity,这里的performResumeActivity会最终回调到我们的activity的onResume方法。
- 上面的handleResumeActivity方法的重点是performResumeAcvitity,在他的内部会调用Activity.performResume方法最终会执行到Activity.onResume方法
- Activity.performResume方法
Activity.performResume中我们是可以看到很多逻辑的,例如:如果我们的activity不是第一次启动调用performResume方法,则会在performResume方法中回调调用performRestart,并且performRestart方法中会同时回调调用performStart方法。这也就是说onRestart和onStart两个方法并不完全是由atms控制的。其中onRestart方法是完全由Activity.onResume方法控制的,而onStart方法只有第一次Activity被启动的时候才会由atms调度控制。
- Instrumentation.callActivityOnResume方法
ViewRootImpl是在哪里初始化的
ViewRootImpl的初始化要从ActivityThread.handleResumeActivity方法开始的
- ActivityThread.handleResumeActivity方法中会调用WindowManagerImpl.addView方法来添加view
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eKZY4ZdM-1653093649667)( “wm的实际类型是WindowManagerImpl”)]
- WindowManagerImpl.addView内部逻辑
WindowManagerImpl.addView内部会调用WindowManagerGlobal.addView来添加View
- WindowManagerGlobal.addView方法
总结
在ActivityThread.handle.handleLaunchActivity方法中,也就是activity创建的过程中会调用Activity.attach方法。在Activity.attach方法中会初始化PhoneWindow,PhoneWindow子view是DecorView,DecorView中的子DecorContentParent是我们布局文件的直接子view。同时会注册callback回调(各种按键事件、触摸事件都是通过这个callback处理),
在onCreate中会调用setContentView方法添加view,我们的setContentView最终会调用Window.setContentView,因为activity中的Window实际类型就是PhoneWindow,所以最终调用的是PhoneWindow.setContentWindow方法。在setContentView方法中会初始化ViewRootImpl对象,他用于管理我们的view
setContentView中的逻辑处理完成后并不是马上把ui展示到页面上。而是需要等待ams回调我们的ActivityThread.handleResumeActivity方法,最终会回调到Activity.onResume方法来展示activity内容的逻辑。
在ActivityThread.handleResumeActivity方法中会调用wms.addView,这里的wms实际类型是WindowManagerImpl继承自IWindowManager(系统服务的老一套了,简单的东西就说一次),在wms.addView中会调用WindowManagerGlobal.addView方法。在WindowManagerGlobal.addView方法中会创建ViewRootImpl对象(ViewRootImpl用于管理我们的布局,并且ViewRootImpl可以监听刷新布局信号,从而刷新布局)。WindowManagerGlobal.addView方法的最后会通过ViewRootImpl.setView方法会把布局添加到Window中。
需要说明的是,这里初始化ViewRootImpl,以及添加window的操作,是只在第一次启动的时候才有的逻辑
后面就到了activity的onResume生命周期的处理逻辑。这里会配合Instrumentation、Activity、ActivityThread完成onResume生命周期的处理。
如果onResume不是第一次被回调,则应用的onRestart、onStart、逻辑都是由activity本身处理的。如果onResume是第一次被回调,则onStart是由atms进行回调处理的。同时onResume最处理onRestart和onStart方法之前,会优先处理onNewIntent和onActivityResult的逻辑(这也解释了为什么onNewIntent和onActivityResult优先于onRestart和onStart执行的逻辑)。