细讲Android中Window、Activity和View之间的关系

一、理解

Activity:就是一个运用程序的承载体,只是界面的承载体,不是界面。用户能够在上面绘制界面(activity
本身不会绘制界面)但是它提供一些用户处理api时间,还有程序的生命周期。
window:首先它是一个抽象类,实现的子类是phoneWindow,在phoneWindow子类中有一个decorView,可以理解成跟视图,
rootView:所以view的二叉树视图都是addView到rootView中去。
View:在android中的View视图就是一颗二叉树,一层嵌套一层,window直接把这个视图加入到decorview中去。

二、查看源码

1、跟踪源码进入到Activity中看到 setContentView的实现如下:

public void setContentView(int layoutResID) {
    getWindow().setContentView(layoutResID);
    initActionBar();
}

看第二行代码,先得到一个 Window 对象。

public Window getWindow() {
        return mWindow;
}

getWindow 很简单只是返回一个对象而已,那么Window对象到底是在哪儿实例化的呢?
我们可以看看,Activity 中的 attach 方法,这里面得到了一个 Window 对象。

mWindow = PolicyManager.makeNewWindow(this);

2、由Activity中的setContentView方法可以看到,界面绘制并不是由 Activity 完成的,他是调用了 Window 类的setContentView来实现的。所以我们就去看看Window类的代码:

public abstract void setContentView(int layoutResID);

我们可以看到,Window类是一个抽象类,并且 setContentView是一个抽象方法。所以说,其具体实现是由实现Window类的类来完成的(PhoneWindow)。

3、在文档中已经描述了:The only existing implementation of this abstract class is android.policy.PhoneWindow. 我们要来看看这个类才能知道 界面是如何完成绘制的。

@Override
public void addContentView(View view,ViewGroup.LayoutParams params) 
{
       if (mContentParent == null) {
           installDecor();
       }
       if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
           // TODO Augment the scenes/transitions API to support this. 8             
           // Log.v(TAG, "addContentView does not support content transitions");
       }
       mContentParent.addView(view, params);
       final Callback cb = getCallback();
       if (cb != null && !isDestroyed()) {
           cb.onContentChanged();
       }
}

先判断mContentParent是否为空,如果为空就调用 installDecor 方法(自己可以看一下源码), 最后会添加 View。

Window 中有一个DecorView,可以理解为“ViewRoot”,引号是说其实这个“ViewRoot”是一个View或者说ViewGroup,是最初始的根视图。构建视图就是向这里面添加。所以到这里大概可以知道installDecor 方法大概是 构建一个根视图。

三、总结

Activity创建时系统会调用其 attach 方法,将其添加到ActivityThread当中,在attach方法中创建了一个window对象。

我们知道Window组合了一个 DocerView, 当用户调用 setContentView 的时候会把一棵 View 树仍给DocerView。 View树是已经创建好的实例对象,所以我们要研究 DocerView是个什么东西,它是如何被创建的。

我们回头看看Window实现里边的setContentView方法,代码中有一个 installDecor 方法,这个方法中有一个 generateDecor。generateDecor直接new了一个DecorView对象。

protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
}

当 DocerView 被创建后,就会调用 mContentParent.addView(view, params); 来将 view 添加到 DocerView当中。

Activity在onCreate时调用attach方法,在attach方法中会创建window对象。window对象创建时并没有创建 DocerView 对象。用户在Activity中调用setContentView,然后调用window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的 View 添加到 DecorView 中。

你可能感兴趣的:(Android,基础)