界面是如何显示的?
如果用最简单的回答,那就是setContentView放入什么布局,界面就长什么样子咯~
关于setContentView的源码,可以自己点进看一下,通俗易懂,十分友好~。。。大体内容就是系统会创建DecorView,然后根据window的相关特性,加载不同的根布局xml,虽然根布局不同,但共同点是都有一个android.id.content的内容区域布局,我们setContentView传入的布局文件,最终会放置在这块内容区。接下里还可以扩展了解下LayoutInflator的解析方法,以及AppCompatActivity对Activity相关方法的升级改造等。
但以上过程只是解决了View的创建和属性配置,深入一点回答这个问题,应该了解View是如何绘制的。
这个稍微懂一点,可以回答View绘制三步骤:Measure,Layout,Draw,以及requestLayout,invalidate。。。
但是,但是,问题来了,通过View的源码可以大致了解到它并不是自己触发自己的绘制的,它的绘制方法public,是由外界调用的。那么,1、谁来调用?2、何时调用?
做个很经典的小实验,进入界面获取view宽高,你会发现onCreate中,得到0,往下一步,onResume,依然是0!这说明首次进入,绘制View的动作甚至在onResume之后~那么。。。
答案隐藏在ActivityThread源码中,看名字就知道ActivityThread是管理界面进进出出各方面的东西,而且,里边居然有main(),java程序的入口!果然很重要的样子~一级一级追代码:
ActivityThread:
handleLaunchActivity
performLaunchActivity
callActivityOnCreate performCreate activity.onCreate
handleResumeActivity
performResumeActivity
activity performResume callActivityOnResume activity.onResume
wm.addView
phoneWindow setWindowManager
WindowManagerImpl
WindowManagerGlobal addView
WindowManagerGlobal root.setView
ViewRootImpl assignParent
ViewRootImpl requestLayout
scheduleTraversals
mTraversalRunnable
doTraversal
performTraversals
performMeasure
performLayout
performDraw 。。。
看完上述步骤,基本上对view的绘制过程已经豁然开朗了。总结来说,ViewRootImpl,这个东西不是view,但它属于ViewParent,是沟通布局和window的桥梁,onResume事件后执行绘制动作的真正幕后黑手!~