雜談。。。

來源:互聯網
上載者:User

View、 window、 Activity

Activity中包含一個honeWindow,調用Acitivity的 setContentView方法的時候實際上是調用的Window對象的setContentView方法,

activity是一個代理,用於顯示、操作window,提供了生命週期和事件等管理window方法,以方便和使用者進行互動。。

window裡面顯示的一個viewgroup,viewgroup繼承view,即window顯示view。。。在viewgroup中包含若干個viewgroup和若干個view

 

Android 中Activity,Window和View之間的關係

我想大多數人,對於這3個東西的概念能區分,但是具體區別在哪卻很難說出來。

我這雷根據我個人的理解來講講我個人對這3個概念的理解。當然這裡設計到通用的事件視窗模型等通用GUI設計,我這裡就不打算講了,純粹從概念上來進行區分。

Activity是Android應用程式的載體,允許使用者在其上建立一個使用者介面,並提供使用者處理事件的API,如onKeyEvent, onTouchEvent等。 並維護應用程式的生命週期(由於android應用程式的運行環境和其他動作系統不同,android的應用程式是運行在架構之內,所以他的應用程式不能噹噹從進程的層級去考慮,而更多是從概念上去考慮。android應用程式是由多個活動堆積而成,而各個活動又有其獨立的生命週期)。Activity本身是個龐大的載體,可以理解成是應用程式的載體,如果木有Activity,android應用將無法運行。也可以理解成android應用程式的入口。Acivity的執行個體對象由系統維護。系統服務ActivityManager負責維護Activity的執行個體對象,並根據運行狀態維護其狀態資訊。

但在使用者層級,程式員可能根願意理解成為一個介面的載體。但僅僅是個載體,它本身並不負責任何繪製。Activity的內部實現,實際上是聚了一個Window對象。Window是一個抽象類別,它的具體是在android_src_home/framework/policies/base/phone/com/android/internal/policy/impl目錄下的PhoneWindow.java。

當我們調用Acitivity的 setContentView方法的時候實際上是調用的Window對象的setContentView方法,所以我們可以看出Activity中關於介面的繪製實際上全是交給Window對象來做的。繪製類圖的話,可以看出Activity彙總了一個Window對象。

下面是PhoneWindow中的setContentView方法的實現:

    @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();

        }

    }

Window內部首先判斷mContentParent是否為空白,然後調用installDecor方法(安裝裝飾器),我們看看這個方法如何?的   

  private void installDecor() {

        if (mDecor == null) {

            mDecor = generateDecor();

            mDecor.setIsRootNamespace(true);

        }

        if (mContentParent == null) {

            mContentParent = generateLayout(mDecor);

            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);

            if (mTitleView != null) {

                if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {

                    View titleContainer = findViewById(com.android.internal.R.id.title_container);

                    if (titleContainer != null) {

                        titleContainer.setVisibility(View.GONE);

                    } else {

                        mTitleView.setVisibility(View.GONE);

                    }

                    if (mContentParent instanceof FrameLayout) {

                        ((FrameLayout)mContentParent).setForeground(null);

                    }

                } else {

                    mTitleView.setText(mTitle);

                }

            }

        }

    }

在該方法中,首先建立一個DecorView,DecorView是一個擴張FrameLayout的類,是所有視窗的根View。我們在Activity中調用的setConctentView就是放到DecorView中了。這是我們類圖的彙總關係如下:

Activity--->Window--->DecorView

這是我們得出這3個類之間最直接的一個關係。

我們詳細分析一下,類對象是如何被建立的。

先不考慮Activity的建立(因為 Acitivity的執行個體由ActivityManager維護,是在另一個進程設計到IPC的通訊,後面會講到),而考慮Window和View的建立。

Activity被建立後,系統會調用它的attach方法來將Activity添加到ActivityThread當中。我們找到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;

    }

我們看紅色的代碼部分,就是建立Window對象的代碼。感興趣的同學可以跟蹤去看看具體是如何建立的。其實很簡單,其內部實現調用了Policy對象的makeNewWindow方法,其方法直接new了一個PhoneWindow對象如下:

public PhoneWindow makeNewWindow(Context context) {

        return new PhoneWindow(context);

 }

這時我們已經可以把流程串起來,Activity建立後系統會調用其attach方法,將其添加到ActivityThread當中,在attach方法中建立了一個window對象。

下面分析View的建立。我們知道Window彙總了DocerView,當使用者調用setContentView的時候會把一顆View樹仍給DocerView.View樹是已經建立好的執行個體對象了,所以我們研究的是DocerView是個什麼東西,它是如何被建立的。

我們回頭看看Window實現裡邊的setContentView方法,我們看上面代碼的紅色部分setContentView-> installDecor-> generateDecor.

generateDecor直接new了一個DecorView對象:  

protected DecorView generateDecor() {

        return new DecorView(getContext(), -1);

 }

我們可以去看看DecorView的實現,它是PhoneWindow的一個內部類。實現很簡單,它預設會包含一個灰色的標題列,然後在標題列下邊會包含一個空白地區用來當使用者調用setContentView的時候放置使用者View,並傳遞事件,這裡不做詳細分析,感興趣同學可以自己研究研究。

當DecorView建立好之後再回到Window中的setContentView方法中來,見上面代碼藍色部分,調用

  mContentParent.addView(view, params);

來將使用者的View樹添加到DecorView中。

到這時為止,我想我們已經很清晰的認識到它們3者之間的關係,並知道其建立流程。

現在總結一下:

Activity在onCreate之前調用attach方法,在attach方法中會建立window對象。window對象建立時並木有建立Decor對象對象。使用者在Activity中調用setContentView,然後調用window的setContentView,這時會檢查DecorView是否存在,如果不存在則建立DecorView對象,然後把使用者自己的View 添加到DecorView中。

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.