android源码宇宙-android的Activity如何展示View

747 阅读3分钟

源码

要点

  1. mContentParent:下文中的mContentParent实际类型是ActionBarOverlayLayout,是我们布局文件的直接父布局
  2. Activity的展示过程大概就是atms回调activity的启动方法,然后会进行初始化PhoneWindow、DecorView。初始化完成后会等待wms回调onResume的逻辑处理,这里的重点是我们的UI展示关键类ViewRootImpl,它就是在这里处理的,最后onResume中会进行activity以下五个回调方法的处理:onNewIntent、onActivityResult、onRestart、onStart、onResume

setContentView流程

  1. Activity.setContentView

image.png

  1. PhoneWindow.setContentView

这里关键的方法就是installDecor方法image.png

  1. 看看installDecor方法

这个方法没有太多的观赏性,因为就是单纯的初始化DecorView和mContentParentimage.png

PhoneWindow是在哪里初始化的

PhoneWindow是在Activity.attach方法中初始化的,代码如下:image.pngimage.png

ActivityThread.handleResumeActivity 处理Activity可见生命周期的理解

我们都知道Activity的生命周期是由atms控制的(低版本是ams),而ViewRootImpl是在onResume中初始化的,进步一onResume向上可以追溯到ActivityThread.handleResumeActivity方法。atms的跨进程调用就是会调用到ActivityThread.handleResumeActivity方法。因此我们的代码就是从ActivityThread.handleResumeActivity方法开始查看。

  1. ActivityThread.handleResumeActivity

如果不是第一次resumeactivity,这里的performResumeActivity会最终回调到我们的activity的onResume方法。

image.png

image.pngimage.pngimage.png

  1. 上面的handleResumeActivity方法的重点是performResumeAcvitity,在他的内部会调用Activity.performResume方法最终会执行到Activity.onResume方法

image.pngimage.png

  1. Activity.performResume方法

Activity.performResume中我们是可以看到很多逻辑的,例如:如果我们的activity不是第一次启动调用performResume方法,则会在performResume方法中回调调用performRestart,并且performRestart方法中会同时回调调用performStart方法。这也就是说onRestart和onStart两个方法并不完全是由atms控制的。其中onRestart方法是完全由Activity.onResume方法控制的,而onStart方法只有第一次Activity被启动的时候才会由atms调度控制。

image.pngimage.png

  1. Instrumentation.callActivityOnResume方法

image.png

ViewRootImpl是在哪里初始化的

ViewRootImpl的初始化要从ActivityThread.handleResumeActivity方法开始的

  1. ActivityThread.handleResumeActivity方法中会调用WindowManagerImpl.addView方法来添加view

image.png

  1. WindowManagerImpl.addView内部逻辑

WindowManagerImpl.addView内部会调用WindowManagerGlobal.addView来添加View

  1. WindowManagerGlobal.addView方法

image.pngimage.pngimage.png

总结

在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执行的逻辑)。