android 中的 window,view,activity具体关系

通过讨论这个问题,我们能够见识到google是对面向对象模式的理解,能够理解android底层的一些调用。这也是一道很常见的面试题。

我们这篇文章就来解决这四个问题:

  • Android  中view的显示视图么?
  • Activity,window,View的关系是什么?
  • LayOutInflater 填充是什么?
  • LayOutInflater 具体怎么做?

首先,我们从activity开始说起,说起activity我们都要知道setcontentview和attach方法。setcontentview中的,主要用来填充相应的布局文件。而至于attach方法了,这个方法用的很少,但是很重要。

我们跟踪java的源代码了,我们清晰的看到这个activity实际上是调用phonewindow的setcontentview中的方法来进行界面的呈现。他的类图如下:

android 中的 window,view,activity具体关系

而phonewindow有初始化了一个ViewGroup对象,这个ViewGroup的子类,可以显示每个控件的视图,还有一个LayoutInflator使xml文件能够填充为相应的视图。他们的类图又是如下:

android 中的 window,view,activity具体关系

我们看看具体的源代码如下:

首先,我们找到activity中的attach方法,这是这个程序启动的时候最重要的方法。了,这是他的源代码:

final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance,
HashMap<String,Object> lastNonConfigurationChildInstances,
Configuration config) {
attachBaseContext(context); mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
mUiThread = Thread.currentThread(); mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstance = lastNonConfigurationInstance;
mLastNonConfigurationChildInstances = lastNonConfigurationChildInstances; mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}

我们看到policymanager对象中有一个window对象,这个window就是现实的窗口了。他是一个抽象类,又是如何new出这个对象,我们继续关注。这就来到了policymanager的类中了。看makenewwindow这个方法:

public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}

他又是传递context调用ipolicy接口中的makeNewWindow方法,来返回一个window对象。继续深挖,我们来看makenewwindow这个方法真实的本来面目。

这个本身的makewindow是ipolicy的一个抽象方法,他是发包给policy实现的,这个policy是new出一个phonewindow对象。  这个phonewindow的类又是怎么样子了。关注源代码我们得知,他是继承与window这个基类的,饶了一大圈以后,发现这个makenewwindow确实是new出一个window的对象。 他构造函数是这个样子:

    public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}

发现他是用一个layoutflater从布局文件中填充一个相应的界面,通过这一大篇源代码证明,我们看到window,activity,和view的关系是这个样子的:
activity中new出一个window,而window通过这个phonewindow子类来获取一个子类。这是一种典型composite模式。一个经典的应用,希望对大家带来帮助。

怎么添加窗口上了,是通过setcontentview方法,我们看到这个还是通过phonewindow的setcontentview方法,他的源代码如下:

    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来添加视图,这更进一步揭示了window与view的关系。

这就是我的理解。

好好学习,天天向上。

上一篇:js变量的生命周期


下一篇:项目分享一:在项目中使用 IScroll 所碰到的那些坑