您的位置:首页 > 移动开发 > Android开发

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

2014-10-11 15:28 357 查看
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图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: