《android開發藝術探索》讀書筆記(八)--WindowManager

來源:互聯網
上載者:User

標籤:記憶體回收   date   接管   pos   die   ams   dispatch   new   步驟   

No1:

Window是一個抽象類別,它的具體實現是PhoneWindow。建立一個Window是很簡單的事,只需要通過WindowManager即可完成。

WindowManager是外界訪問Window的入口,Window的具體實現位於WindowManagerService中,WindwoManager和WindowManagerService的互動時一個IPC過程。

Android中所有的視圖都是通過Window來呈現的,因此Window實際是View的直接管理者。

單機事件由Window傳遞給DecorView,然後再由DecorView傳遞給我們的View。

No2:

Window有三種類型,分別是應用Window、子Window和系統Window。

應用Window--一個Activity

子Window--不能單獨存在,需要附屬在特定的父Window中,比如Dialog

系統Window--是需要聲明許可權才能建立的Window,比如Toast和系統狀態列

No3:

Window是分層的,每個Window都有對應的z-ordered,層級大的會覆蓋在層級小的Window的上面。

應用程式層Window層級範圍1~99

子Window層級範圍1000~1999

系統Window層級範圍2000~2999

這些層級範圍對應著WindowManager.LayoutParams的type參數。如果想要Window位於所有Window的最頂層,那麼採用較大的層級即可。

No4:

WindowManager所提供的功能很簡單,常用的只有三個方法,添加ViewaddView、更新ViewupdateViewLayout和刪除ViewremoveView,這三個方法定義在ViewManager中,而WindowManager繼承了ViewManager。

No5:

可以拖動的Window效果

public boolean onTouch(View v,MotionEvent event){    int rawX = (int)event.getRawX();    int rawY = (int)event.getRawY();    switch(event.getAction()){        case MotionEvent.ACTION_MOVE:            mLayoutParams.x = rawX;            mLayoutParams.y = rawY;            mWindowManager.updateViewLayout(mFloationButton,mLayoutParams);            break;        default:            break;    }    return false;}

No6:

Window是一個抽象的概念,每個Window都對應著一個View和一個ViewRootImpl,Window和View通過ViewRootImpl來建立串連,因此Window並不是實際存在的,它是以View的形式存在。

在實際使用中無法直接存取Window,對Window的訪問必須通過WindowManager。

No7:

WindowManager是一個介面,它的真正實現是WindowManagerImpl類。WindowManagerImpl並沒有直接實現Window的三大操作,而是全部交給了WindowManagerGlobal來處理。

WindowManagerImpl這種工作模式是典型的橋接模式。

No8:

Window的添加過程

1.檢查參數是否合法,如果是子Window那麼還需要調整一些布局參數

2.建立ViewRootImpl並將View添加到列表中

3.通過ViewRootImpl來更新介面並完成Window的添加過程

View的繪製過程是由ViewRootImpl來完成的,在setView內部會通過requestLayout完成非同步重新整理請求,scheduleTraversals實際是View繪製的入口,接著會通過WindowSession最終來完成Window的添加過程,真正的實作類別是Session,也就是Window的添加過程是一次IPC調用,在Session內部會調用WindowManagerService來實現Window的添加。

No9:

Window的刪除過程

WindowManagerImpl-->WindowManagerGlobal-->ViewRootImpl

WindowManager中提供了兩種刪除介面removeView和removeViewImmediate,分別表示非同步刪除和同步刪除。

非同步刪除具體的刪除操作由ViewRootImpl的die方法來完成,die發送了一個請求刪除的訊息,ViewRootImpl中的Handler會處理此訊息並調用doDie方法,如果是同步刪除,那麼就不發訊息直接調用doDie方法。

doDie內部會調用dispatchDetachedFromWindow方法,dispatchDetachedFromWindow主要做四件事:

1)記憶體回收相關工作,比如清除資料和訊息、移除回調

2)通過Session的remove方法刪除Window:mWindowSession.remove(mWindow),這同樣是一個IPC過程,最終會調用WindowManagerService的removeWindow方法

3)調用View的dispatchDetachedFromWindow方法,在內部會調用View的onDetachedFromWindow()以及onDetachedFromWindowInternal()。

當View從Window中移除時,這個方法就會被調用,可以在這個方法內部做一些資源回收的工作,比如終止動畫、停止線程等

4)調用WindowManagerGolbal的doRemoveView方法重新整理資料,包括mRoots、mParams以及mDyingViews,需要將當前Window所關聯的這三類對象從列表中刪除。

No10:

Window的更新過程:還是要看WindowManagerGlobal的updateViewLayout方法:

1)通過ViewRootImpl的setLayoutParams更新View的LayoutParams並替換掉老的LayoutParams,接著再更新ViewRootImpl中的LayoutParams

2)在ViewRootImpl中會通過scheduleTraversals方法來對View重新布局,包括測量、布局、重繪這三個過程

3)ViewRootImpl還會通過WindowSession來更新Window視圖,最終是由WindowManagerService的relayoutWindow()來具體實現的。同樣是一個IPC過程

No11:

Window對象的建立是通過PolicyManager的makeNewWindow方法實現的。PolicyManager的真正實現是Policy類,所以Window的具體實現的確是PhoneWindow。

No12:

setContentView:Activity-->Window-->PhoneWindow

No13:

DecorView是一個FrameLayout,是Activity中的頂級View,一般包括標題列和內部欄

No14:

Activity的Window的建立過程

PhoneWindow的setContentView步驟

1)如果沒有DecorView,那麼就建立它

2)將View添加到DecorView的mContentParent中(這就是為Activity的setContentView而不叫setView的緣由

3)回調Activity的onContentChanged方法通知Activity視圖已經發生改變

No15:

在ActivityThread的makeVisible()方法中,首先會調用Activity的onResume方法,接著會調用Activity的makeVisible(),正是在makeVisible方法中,DecorView真正地完成了添加和顯示這兩個過程,到這裡Activity的視圖才能被使用者看到。

No16:

Dialog的Window建立過程

1)建立Window

2)初始化DecorView並將Dialog的視圖添加到DecorView中

3)將DecorView添加到Window中並顯示

No17:

普通Dialog有一個特殊之處,就是必須採用Activity的Context,如果採用Application的Context,會報錯沒有token,而應用token一般只有Activity擁有。

系統Window不需要token,因此只要指定對話方塊為Window為系統類別型即可

No18:

Toast具有定時取消這一功能,所以系統採用了Handler。

Toast內部有兩類IPC過程,第一類是Toast訪問NotificationManagerService,第二類是NotificationManagerService回調Toast裡面的TN介面。

顯示和隱藏Toast都需要通過NotificationManagerService來實現,因為NMS運行在系統進程中,所以只能通過遠程調用的方式來顯示和隱藏。TN是一個Binder類,它運行在Binder線程池中,所以需要Handler將其切換到當前線程中,這裡的當前線程是指發送Toast請求所在的線程。

No19:

enqueueToast首先將Toast請求封裝為ToastRecord對象並將其添加到一個名為mToastQueue的隊列中。mToastQueue其實是一個ArrayList。對於非系統應用來說,mToastQueue中最多能同時存在50個ToastRecord。如果不這樣做,將導致其他引用沒有機會彈出Toast。

No20:

Toast延時相應時間後,NotificationManagerService會通過cancelToastlocked方法來隱藏Toast並將其從mToastQueue中移除,這個時候如果mToastQueue中還有其他Toast,那麼NMS就繼續顯示其他Toast。Toast的隱藏也是通過ToastRecord的callback來完成的,這同樣也是一次IPC過程。

No21:

Toast中TN的兩個方法show和hide,是以NMS以跨進程的方式調用的,因此它們運行在Binder線程池中。

《android開發藝術探索》讀書筆記(八)--WindowManager

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.