通過討論這個問題,我們能夠見識到google是對面向對象模式的理解,能夠理解android底層的一些調用。這也是一道很常見的面試題。
我們這篇文章就來解決這四個問題:
- Android 中view的顯示視圖么?
- Activity,window,View的關系是什么?
- LayOutInflater 填充是什么?
- LayOutInflater 具體怎么做?
首先,我們從activity開始說起,說起activity我們都要知道setcontentview和attach方法。setcontentview中的,主要用來填充相應的布局文件。而至於attach方法了,這個方法用的很少,但是很重要。
我們跟蹤java的源代碼了,我們清晰的看到這個activity實際上是調用phonewindow的setcontentview中的方法來進行界面的呈現。他的類圖如下:

而phonewindow有初始化了一個ViewGroup對象,這個ViewGroup的子類,可以顯示每個控件的視圖,還有一個LayoutInflator使xml文件能夠填充為相應的視圖。他們的類圖又是如下:

我們看看具體的源代碼如下:
首先,我們找到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的關系。
這就是我的理解。
好好學習,天天向上。
