补充说明Window、PhoneWindow与DecorView

来源:互联网 发布:java编译器中文安卓版 编辑:程序博客网 时间:2024/06/05 15:31

我们大概理解了View/ViewGroup的概念。但是它们仅仅是界面的一部分,正如下图所示:

对相关类的作用进行一下简单介绍:

  • Window 类   位于 /frameworks/base/core/java/android/view/Window.java。该类是一个抽象类,提供了绘制窗口的一组通用API。可以将之理解为一个载体,各种View在这个载体上显示。
  • PhoneWindow类  位于/frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindow.java。该类继承于Window类,是Window类的具体实现,即我们可以通过该类具体去绘制窗口。并且,该类内部包含了一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View。 简而言之,PhoneWindow类是把一个FrameLayout类即DecorView对象进行一定的包装,将它作为应用窗口的根View,并提供一组通用的窗口操作接口。
  • DecorView类    该类是PhoneWindow类的内部类。该类是一个FrameLayout的子类,并且是PhoneWindow的子类,该类就是对普通的FrameLayout进行功能的扩展,更确切点可以说是修饰(Decor的英文全称是Decoration,即“修饰”的意思),比如说添加TitleBar(标题栏),以及TitleBar上的滚动条等 。最重要的一点是,它是所有应用窗口的根View 。

打个不恰当比喻吧,Window类相当于一幅画(抽象概念,什么画我们未知) ,PhoneWindow为一副齐白石先生的山水画(具体概念,我们知道了是谁的、什么性质的画),DecorView则为该山水画的具体内容(有山、有水、有树,各种界面)。DecorView呈现在PhoneWindow上。

当系统(一般是ActivityManagerService)配置好启动一个Activity的相关参数(包括Activity对象和Window对象信息)后,就会回调Activity的onCreate()方法,在其中我们通过设置setContentView()方法类设置该Activity的显示界面,整个调用链由此铺垫开来。setContentView()的三个构造方法调用流程本质上是一样的,我们就分析setContentView(intresId)方法。

Activity.setContentView(intresId) 该方法在Activity类中,该方法只是简单的回调Window对象,具体为PhoneWindow对象的setContentView()方法实现。

1public void setContentView(int layoutResID) { 
2    getWindow().setContentView(layoutResID); 
3
4   
5public Window getWindow() { 
6    return mWindow;   //Window对象,本质上是一个PhoneWindow对象 
7

PhoneWindow.setContentView() 该方法在PhoneWindow类中

01@Override 
02public void setContentView(int layoutResID) { 
03    //是否是第一次调用setContentView方法, 如果是第一次调用,则mDecor和mContentParent对象都为空 
04    if (mContentParent == null) { 
05        installDecor(); 
06    else 
07        mContentParent.removeAllViews(); 
08    
09    mLayoutInflater.inflate(layoutResID, mContentParent); 
10    final Callback cb = getCallback(); 
11    if (cb != null) { 
12        cb.onContentChanged(); 
13    
14

该方法根据首先判断是否已经由setContentView()了获取mContentParent即View对象, 即是否是第一次调用该PhoneWindow对象setContentView()方法。如果是第一次调用,则调用installDecor()方法,否则,移除该mContentParent内所有的所有子View。最后将我们的资源文件通过LayoutInflater对象转换为View树,并且添加至mContentParent视图中。

因此,在应用程序里,我们可以多次调用setContentView()来显示我们的界面。

View的measure过程由其measure方法来完成,measure方法是一个final类型的方法,这意味着子类不能重写此方法,在View的measure方法中会调用View的onMeasure方法。对于ViewGroup来说,除了完成自己的measure过程以外,还会遍历去调用所有子元素的measure方法,各个子元素再递归去执行这个过程。和View不同的是,ViewGroup是一个抽象类,因此他没有重写View的onMeasure方法,但是他提供了一个叫measureChildren的方法。View与ViewGroup均提供了layout和onLayout方法,但onLayout方法一个是空实现的,一个是抽象的。View的绘制过程的传递是通过dispatchDraw来实现的。

0 0
原创粉丝点击