Android 之 Window、WindowManager 與視窗管理

yangxi_001發表於2013-11-15

其實在android中真正展示給使用者的是window和view,activity在android中所其的作用主要是處理一些邏輯問題,比如生命週期的管理、建立視窗等。在android中,視窗的管理還是比較重要的一塊,因為他直接負責把內容展示給使用者,並和使用者進行互動。響應使用者的輸入等。

在講視窗管理時,有必要先說下ViewManager這個介面,這個介面主要有以下的實現子介面和實現類,分別是:WindowManagerViewGroup裡面還有三個重要的方法:

      * addView(); 

     * updateViewLayout();

     * removeView();

WindowManager中,addView方法表示的是將主視窗中的頂級view(也就是DecorView)新增到WindowManager中,並建立會話。接下來會詳細介紹。我們先來看看Window

Window:

Windowandroid中的視窗,表示頂級視窗的意思,也就是主視窗,它有兩個實現類,PhoneWindowMidWindow,我們一般的activity對應的主要是PhoneWindow,在activity中經常使用的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();  //視窗類容發生變化時更新

        }

    }

 每個主視窗中都有一個View,稱之為DecorView,是主視窗中的頂級view(實際上就是ViewGroup),在View中有兩個成員變數叫做mParent、mChildren,它是用來管理view的上下級關係的。而ViewGroup是對一組View的管理。因此,在ViewGroup中建立了所有view的關係網。而最終ViewGroup附屬在主視窗上。這樣就很容易在視窗中通過findViewById找到具體的View了。view中的事件處理也是根據這個路徑來處理的。

我們再來看看ActivityThead中的兩個重要的方法(至於ActivityThead將在一篇中詳細介紹)

           performLaunchActivity( );

            handleResumeActivity( );

performLaunchActivity中,會呼叫activity.attach方法建立一個window, 在handleResumeActivity方法中啟動activity的時候,會將主視窗加入到WindowManager

             View decor =r.window.getDecorView();  //獲得視窗的頂級View

      decor.setVisibility(View.INVISIBLE);

      ViewManager wm= a.getWindowManager();    //WindowManager繼承自ViewManager

      WindowManager.LayoutParams l =r.window.getAttributes();

      a.mDecor = decor;

      l.type =WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

     l.softInputMode |= forwardBit;

     if (a.mVisibleFromClient) {

         a.mWindowAdded = true;

         wm.addView(decor, l);  //實際上是把主視窗的頂級view加入到WindowMangaer

      }

我們再來看看WindowManager

WindowManager:

WindowManager主要用來管理視窗的一些狀態、屬性、view增加、刪除、更新、視窗順序、訊息收集和處理等。

通過Context.getSystemService(Context.WINDOW_SERVICE)的方式可以獲得WindowManager的例項.

WindowManager繼承自ViewManager,裡面涉及到視窗管理的三個重要方法,分別是:

     * addView(); 

     * updateViewLayout();

     * removeView();  

WindowManager中還有一個重要的靜態類LayoutParams.通過它可以設定和獲得當前視窗的一些屬性。

我們先來看看addView()方法,在addView中,會利用LayoutParams獲得windowView屬性,併為每個window建立ViewRootViewRootViewWindowManager之間的橋樑,真正把View傳遞給WindowManager的是通過ViewRootsetView()方法,ViewRoot實現了ViewWindowManager之間的訊息傳遞。在將主視窗新增到WindowManger時,它首先會建立一個代理物件:

              wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE)

並且開啟會話(IWindowSession),之後Window將通過該會話與WindowManager建立聯絡,

來看下setView方法:

         try {

        res =sWindowSession.add(mWindow, mWindowAttributes,

         getHostVisibility(), mAttachInfo.mContentInsets);

     } catch (RemoteException e) {

         mAdded = false;

        mView = null;

         mAttachInfo.mRootView =null;

         unscheduleTraversals();

         throw newRuntimeException("Adding window failed", e);

      } finally {

         if (restore) {

            attrs.restore();

         }

      }

在這段程式碼中,ViewRoot通過IWindowSession把視窗新增到WindowManager中。ViewRoot繼承了Handler,實際上它的本質就是一個Handler,視窗中View的事件處理、訊息傳送、回撥等將通過ViewRoot來處理。

這樣就完成了把視窗新增到WindowManager中,並交由WindowManager來管理視窗的view、事件、訊息收集處理等。

相關文章