android 中的 window,view,activity具體關系


通過討論這個問題,我們能夠見識到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的關系。

這就是我的理解。

好好學習,天天向上。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM