5.在performMeasure中又会调用view的measure方法,performLayout和performDraw方法也会相继调用view的layout方法和draw方法。其中measure用来测量view的宽和高,layout用来确定view在父容器中的放置位置,而draw则用来负责将view绘制在屏幕上。
6.对于测量过程,在ViewRootImpl的performMeasure方法中,实际上这里的view指的是顶级view,即DecorView,因此这里会相继调用DecorView的measure->onMeasure方法,在DecorView的onMeasure方法中又调用了FrameLayout的onMeasure方法,即:super.onMeasure(),接着就来到了viewGroup中,viewGroup会遍历其每一个子view,并调用子view的measure()来完成测量过程,而子view的测量又是和viewGroup的measureSpec以及子view的layoutParams来确定自身的宽和高的。
接下来再对具体过程具体分析。首先在所有程序的入口main函数里会先创建activityThread:
public static void main(String[] args) { Looper.prepareMainLooper(); // 创建ActivityThread实例 ActivityThread thread = new ActivityThread(); thread.attach(false); ....... } 而ActivityThead中的handleLaunchActivity中有两个重要的方法(至于ActivityThead将在另一篇博客中详细介绍),performLaunchActivity( )和handleResumeActivity( )。在performLaunchActivity( )中会调用activity的attach方法来建立一个窗口,而handleResumeActivity( )则会在启动activity的时候,将主窗口加入到windowManager中来实现窗口管理,来看部分源代码: private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { ........... Activity a = performLaunchActivity(r, customIntent); if (a != null) { ............. handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason); } } 函数首先调用ActivityThread类的成员函数performLaunchActivity来创建要启动的Activity组件。在创建Activity组件的过程中,还会为该Activity组件创建窗口对象和视图对象。Activity组件创建完成之后,就可以将它激活起来了,这是通过调用ActivityThread类的成员函数handleResumeActivity来执行的。接下来,我们首先分析ActivityThread类的成员函数performLaunchActivity,它主要功能就是创建一个activity组件实例,并且调用这个activity组件实例的成员函数onCreate来执行一些自定义的初始化工作(onCreate方法就是在这里被调用的!) 接下来我们就来看看我们最熟悉的onCreate方法: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ...... } public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); } getWindow().setContentView(layoutResID)实际上就是调用PhoneWindow对象的setContentView方法: public void setContentView(int layoutResID) { // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window // decor, when theme attributes and the like are crystalized. Do not check the feature // before this happens. if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { mLayoutInflater.inflate(layoutResID, mContentParent); } mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } mContentParentExplicitlySet = true; } PhoneWindow类的成员变量mContentParent用来描述一个类型为DecorView的视图对象,或者这个类型为DecorView的视图对象的一个子视图对象,用作UI容器。当它的值等于null的时候,就说明正在处理的应用程序窗口的视图对象还没有创建。在这种情况下,就会调用成员函数installDecor来创建应用程序窗口视图对象。否则的话,就说明是要重新设置应用程序窗口的视图。在重新设置之前,首先调用成员变量mContentParent所描述的一个ViewGroup对象来移除原来的UI内容。 如果假设此时mContentParent为nulll,此时会调用installDecor来创建DecorView视图对象,接着再通过调用PhoneWindow类的成员变量mLayoutInflater所描述的一个LayoutInflater对象的成员函数inflate来将参数layoutResID所描述的一个UI布局,并设置到前面所创建的应用程序窗口视图中去(DecorView),最后还会调用一个Callback接口的成员函数onContentChanged来通知对应的Activity组件,它的视图内容发生改变了。Activity组件自己实现了这个Callback接口,并且将这个Callback接口设置到了与它所关联的应用程序窗口对象的内部去,因此,前面实际调用的是Activity类的成员函数onContentChanged来发出一个视图内容变化通知。 在installDecor函数中,会调用generateDecor来创建一个DecorView对象,并且保存在PhoneWindow类的成员变量mDecor中。紧接着installDecor又会调用generateLayout来根据当前应用程序窗口的Feature来加载对应的窗口布局文件(就是在layout目录下的布局文件),通过generateLayout能够创建一个应用程序窗口视图。 这一步完成之后(即窗口视图创建起来之后),回到ActivityThread类的成员函数handleLaunchActivity中的handleResumeActivity之中,该方法用来激活正在启动的activity组件,由于是第一次激活该组件,因此在激活之前还会为该activity组件创建一个ViewRoot对象(主角登场),并将ViewRoot与前面所创建的应用程序视图窗口关联起来,以便后面通过该ViewRoot对象来控制应用程序窗口视图的UI展现。