本文已經收錄到個人Github我的博客,歡迎大佬們光臨寒舍:java
個人GIthub博客android
Window&WindowManagerServicegit
Window&WindowManagergithub
Window&PhoneWindowsegmentfault
Window&Activityapp
Window&Viewide
Window內部機制函數
Window建立過程佈局
Window
?Android手機上全部的視圖都是經過Window
來呈現的,像經常使用的Activity
,Dialog
,PopupWindow
,Toast
,他們的視圖都是附加在Window
上的,因此能夠這麼說 ——「Window是View的直接管理者」。post
Window
是一個頂層窗口查看和行爲的一個抽象基類,這個類的實例做爲一個頂級View
添加到Window Manager
。它提供了一套標準的UI方法,好比添加背景,標題等等。
Window
自己很抽象,深刻了解Window
,不只有助於你瞭解Android
系統中各個層級之間的關係,還能夠對Toast
的內部機制、自定義等等方面會有更加深刻的體會。
看到下面這張大圖,是否是感受有點亂亂的,別急,別急,心急吃不了熱豆腐,筆者將向您娓娓道來
Window
&PhoneWindow
筆者以前在進階之路 | 奇妙的View之旅中,說起
setContentView
的時候簡單說到了Window
和PhoneWindow
,相信看過的讀者已經對此有一個簡單的印象。
Window
是一個抽象類,它定義了頂級窗體樣式和行爲。其惟一的實現類是PhoneWindow
。
Window
&View
筆者以前在進階之路 | 奇妙的View之旅中,說起
View工做流程
的時候簡單說到了ViewRootImpl
,相信看過的讀者已經對此有一個簡單的印象。
每一個Window
都對應一個View
和一個ViewRootImpl
,Window
和View
經過ViewRootImpl
來創建聯繫。Window並不可見,它實際以View的形式存在,它是View
的直接管理者。
Window
&WindowManagerService
想了解IPC的讀者,能夠看下筆者寫的一篇博客: 進階之路 | 奇妙的 IPC 之旅
Window的具體實現位於WindowManagerService
中。WindowManager
和WindowManagerService
的交互是一個IPC
(跨進程通訊)過程。
Window
&WindowManager
實際使用中沒法訪問Window
,對Window
的訪問必須經過WindowManager
(換句話說,WindowManager
是外界訪問Window
的入口),對Window
的操做經過它完成。
WindowManager
添加Window
//將一個Button添加到屏幕爲(100,300)的位置
mFloatingButton = new Button(this);
mFloatingButton.setText("test button");
mLayoutParams = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0,PixelFormat.TRANSPARENT);//第三個參數表明flags,第四個參數表明type
mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_SHOW_WHEN_LOCKED;//配置flags
mLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;//配置type
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;//配置gravity
mLayoutParams.x = 100;//相對於gravity
mLayoutParams.y = 300;//相對於gravity
mFloatingButton.setOnTouchListener(this);
mWindowManager.addView(mFloatingButton, mLayoutParams);
複製代碼
下面依次介紹WindowManager
的三個重要參數:
flags
:表示Window的屬性。主要的可選值含義:
FLAG_NOT_FOCUSABLE
:表示Window
不須要獲取焦點,也不須要接收各類輸入事件,此標記會同時啓動FLAG_NOT_TOUCH_MODEL
,最終事件會傳遞給下層的具備焦點的Window
。FLAG_NOT_TOUCH_MODAL
:表示系統會將當前Window區域之外的單擊事件傳遞給底層的Window,而區域之內的單擊事件則本身處理。通常都須要開啓此標記,不然其餘Window將沒法收到單擊事件。FLAG_SHOW_WHEN_LOCKED
:表示Window可顯示在鎖屏界面。
type
:表示Window
的類型。Window
有三種類型:
A.應用類Window
:對應一個Activity
B.子Window:不能單獨存在,需附屬特定的父Window。如Dialog
C.系統Window: 需聲明權限才能建立。如Toast
系統權限有不少值,通常選用:TYPE_SYSTEM_OVERLAY
/TYPE_SYSTEM_ERROR
記得聲明權限:< uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
,Android
6.0如下直接聲明權限便可,Android6.0
以上還須要用戶打開軟件設置頁手動打開,才能受權。
Window
是分層的,見下表- 層級大的會覆蓋在層級小的Window上面。
- 對應WindowManager.LayoutParams的type參數。
Window | 層級 |
---|---|
應用Window | 1-99 |
子Window | 1000-1999 |
系統Window | 2000-2999 |
gravity
:表示Window
的位置。
- 默認是屏幕中間
- x、y值相對於gravity
WindowManager
對Window
主要有三大操做:添加、更新和刪除。
這三個方法主要是定義在ViewManager
接口中:
public interface ViewManager {
public void addView(View view, ViewGroup.LayoutParams params);//添加過程
public void updateViewLayout(View view, ViewGroup.LayoutParams params);//更新過程
public void removeView(View view);//刪除過程
}
複製代碼
WindowManager
也是一個接口,它繼承了ViewManager
接口:public interface WindowManager extends ViewManager {}
複製代碼
WindowManager
的具體實現類是WindowManagerImpl
:public final class WindowManagerImpl implements WindowManager{
@Override
public void addView(View view, ViewGroup.LayoutParams params){
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
@Override
public void updateViewLayout(View view, ViewGroup.LayoutParams params){
mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view){
mGlobal.removeView(view, false);
}
}
複製代碼
WindowManagerImpl
並無直接實現Window的三大操做,而是交給了WindowManagerGlobal
。WindowManagerGlobal
以單例模式向外提供本身的實例:
WindowManagerImpl
這種工做模式是典型的橋接模式
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
複製代碼
一幅圖說明這幾個類的關係:
所以,經過
WindowManagerGlobal
的addView()
、updateViewLayout()
、removeView()
實現WindowManager
對Window
的添加、刪除和修改。
Window
的添加Window
的刪除Window
的更新不難發現,以上驗證了以前的總結:
Window
的三大操做最終都會經過一個IPC過程移交給WindowManagerService
。Window
和View
經過ViewRootImpl
來聯繫,ViewRootImpl
可控制View
的測量、佈局和重繪。
限於篇幅,筆者這裏暫未貼上源碼,若是想了解的話,推薦一篇文章:我眼中的Window建立/添加/刪除/更新過程
Window
的建立過程因爲
View
必須依附Window
才能呈現出來,所以有View
的地方必有Window
。在Android
中能夠提供View
的地方有Activity
、Dialog
和Toast
,PopupWindow
,菜單
,下面分別來看Activity
、Dialog
和Toast
三種Window
的大體建立過程:
Activity
的Window
建立過程
Activity
的啓動流程這裏不瞭解不要緊,筆者後面會專門寫一篇文章來介紹
想了解
Activity
的Window
建立過程的源碼的讀者,筆者推薦一篇文章: Activity的Window建立過程分析
Dialog
的Window
建立過程Dialog.show()
方法:完成DecorView
的顯示WindowManager.remoteViewImmediate()
方法:當Dialog被dismiss
時移除DecorViewToast
的Window
建立過程Q1:Toast的內部的視圖由兩種方式指定:
setView()
指定一個自定義ViewQ2:Toast
具備定時取消功能,故系統採用Handler
作定時處理
Q3:在Toast
內部有兩類IPC過程:
Toast
訪問NotificationManagerService()
(NotificationManagerService
運行在系統的進程);NotificationManagerService
回調Toast
裏的TN
接口(運行在Binder
線程池)。Q4:Toast
提供方法show()
和cancel()
分別用於顯示和隱藏Toast
。
Toast
的顯示和隱藏都須要經過NMS
來實現,因爲NMS
運行在系統進程中,故需經過遠程調用的方式來進行顯示和隱藏Toast。NMS
處理Toast
的顯示和隱藏請求時會跨進程回調TN
中的方法,可是因爲TN
運行在Binder線程池中,故需經過Handler
將其切換到當前線程(發送Toast請求的線程)。
NMS
只是起到了管理Toast
隊列及其延時的效果Toast
的顯示和隱藏實際是經過TN
來實現的。
想了解
Toast
的Window
建立過程的源碼的讀者,筆者推薦一篇文章:Android對話框Dialog,PopupWindow,Toast的實現機制
恭喜你!已經看完了前面的文章,相信你對
Window
已經有必定深度的瞭解,下面,進行一下課堂小測試,驗證一下本身的學習成果吧!
Q1:一個應用中有多少個Window?
答案:無限個。緣由:任何一個View
都是依附在Window
上面,一個應用能夠有無限個View
,天然Window
也是無限個。
Q2:Window對象有存在的必要嗎?
Window
能作的事情,View
對象基本都能作:像觸摸事件、管理各個子View
等等。Window
是View
的管理者」。WindowManager
是Window
的管理者,那爲何不直接用WindowManager
管理View
呢?View
對象這個說法的!做爲系統,我有本身的驕傲,不去管你Window
如何搬磚、如何砌牆,只給你地皮。而這時,Window
爲了繪製出用戶想要的組件(按鈕、文字、輸入框等等),系統又不給我!沒事,那我本身定義,因而就定義了View
機制,給每一個View
提供Canvas
,讓不一樣的View本身繪製具備本身特點的組件。同時,爲了更好的管理View
,經過定義ViewGroup
,等等。Q3:Activity有存在的必要嗎?
Window
已是系統管理的窗口界面。那麼爲何還須要Activity
呢?咱們把Activity
所作的事情,所有封裝到Window
不就行了?懸浮窗口Dialog
中不就是沒有使用Activity
來顯示一個懸浮窗嗎?Android
中的應用中,裏面對各個窗口的管理至關複雜(任務棧、狀態等等)。可是若是讓用戶本身去管理這些Window
,先不說工做量,光讓用戶本身去實現任務棧這點,就很難了。爲了讓你們能簡單、快速的開發應用,Android
讓Activity
幫咱們管理好,咱們只需簡單的去重寫幾個回調函數,無需直接與Window
對象接觸。任何事物都有規律,語言再難,也是人發明的,同樣具備社會性,其實這幾個的關係就像是國家的中央系統的官員分配同樣,從古至今,一層對一層負責,這樣各司其職,又相互一層層聯繫着,達到效率最大化,忽然發現,古人的智慧仍是很厲害的,你讓皇帝(系統)去管轄全部的官員(view),豈不是要累死?因此纔出現了中間這些「官員」
若是文章對您有一點幫助的話,但願您能點一下贊,您的點贊,是我前進的動力
本文參考連接: