Android中Activity,View,Window之间的关系

1.首先来看Activity中的attach()方法,在调用onCreate()之前会调用attach(),在这里我们先不管是谁调用这个方法。下面来看一下代码片段(Activity.java):

// attach()中的一个语句,返回一个Window对象
mWindow = PolicyManager.makeNewWindow(this);

 从上面可以看到attach()方法调用PolicyManager.makeNewWindow(this),得到了一个Window对象(实际上是PhoneWindow对象,Window是一个抽象类),而PolicyManager则利用Policy中的makeNewWindow()方法返回一个PhoneWindow对象。请看下面的代码片段(PolicyManager.java):

// sPolicy为Policy对象,实现了接口IPolicy
    public static Window makeNewWindow(Context context) {
        return sPolicy.makeNewWindow(context);
    }

 再看下面的代码(Policy.java):

// 这里就是返回了一个PhoneWindow对象
public PhoneWindow makeNewWindow(Context context) {
        return new PhoneWindow(context);
    }
 

所以,在一个Activity构造的时候,一定会构造一个Window对象,并且只有一个。上面的一些代码就是实例化了一个Window。Window对象的作用下面会提到。


2.下面我们来看setContentView()方法,这是它的代码片段(Activity.java,有三个重载的方法):

 /**
     * Set the activity content from a layout resource.  The resource will be
     * inflated, adding all top-level views to the activity.
     * 
     * @param layoutResID Resource ID to be inflated.
     */
    public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
    }

    /**
     * Set the activity content to an explicit view.  This view is placed
     * directly into the activity's view hierarchy.  It can itself be a complex
     * view hierarhcy.
     * 
     * @param view The desired content to display.
     */
    public void setContentView(View view) {
        getWindow().setContentView(view);
    }

    /**
     * Set the activity content to an explicit view.  This view is placed
     * directly into the activity's view hierarchy.  It can itself be a complex
     * view hierarhcy.
     * 
     * @param view The desired content to display.
     * @param params Layout parameters for the view.
     */
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        getWindow().setContentView(view, params);
    }

从上面的代码中可以知道,这三个重载的方法,都是调用了getWindow().setContentView(),而getWindow()方法就是返回一个Window对象(就是前面attach得到的一个PhoneWindow对象,引用变量是mWindow),接下来我们定位到PhoneWindow中(PhoneWindow.java):

 
// 跟Activity中的三个重载方法是意义对应的
@Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    }

    @Override
    public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mContentParent.addView(view, params);
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    }

 在上面三个方法中,我们要看是两个引用变量:mContentParent,mLayoutInflater。分别是ViewGroup对象和LayoutInflater对象。这个是mContentParent就是Winodw的ViewRoot(根视图,这是逻辑性的根视图,实际就是View或ViewGroup),通过mContentParent.addView()来添加各种View,达到我们所要的效果。其实,Activity就是一个控制单元,而Window本身不是一个视图(View),Window就是一个承载模型,而View才是真正的显示视图。而LayoutInflater的作用是把资源文件(布局文件)加载成一个View(使用LayoutInflaterd的inflate(int resource, ViewGroup root)方法)。

3.WindowManagerService接受的消息,并且回调Activity函数,onKeyDown()....

4.如何动态的添加一个layout并且显示出来,请看下面的代码片段:

	
// 这里跳过了Activity的setContentView()方法
	getWindow().setContentView(LayoutInflater.from(this).inflate(R.layout.main, null));
 

下面再传一张UML图:

猜你喜欢

转载自rhythm-of-rain.iteye.com/blog/1726676
今日推荐