多數(shù)情況我們是和Activity和View打交道洗鸵,在之前學(xué)習(xí)中也都接觸過,本篇來深入學(xué)習(xí)和它們有緊密聯(lián)系的Window椿息,主要內(nèi)容:
- Window&WindowManager
- Window的內(nèi)部機制(添加涛菠、刪除铺然、更新)
- Window的創(chuàng)建過程(Activity、Dialog且轨、Toast)
1.Window&WindowManager
a.Window&PhoneWindow:
Window是一個抽象類糕殉,它定義了頂級窗體樣式和行為。其唯一的實現(xiàn)類是PhoneWindow殖告。
推薦閱讀:Window阿蝶,PhoneWindow,DecorView黄绩,setContentView源碼理解
b.Window&View:
每個Window都對應(yīng)一個View和一個ViewRootImpl羡洁,Window和View通過ViewRootImpl來建立聯(lián)系。Window并不可見爽丹,它實際以View的形式存在筑煮,它是View的直接管理者。
c.Window&WindowManager:
實際使用中無法訪問Window粤蝎,對Window的訪問必須通過WindowManager真仲,對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);//第三個參數(shù)代表flags初澎,第四個參數(shù)代表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的三個重要參數(shù):
-
flags:表示W(wǎng)indow的屬性秸应。主要的可選值含義:
- FLAG_NOT_FOCUSABLE:表示W(wǎng)indow不需要獲取焦點,也不需要接收各種輸入事件碑宴,此標(biāo)記會同時啟動FLAG_NOT_TOUCH_MODEL软啼,最終事件會傳遞給下層的具有焦點的Window。
- FLAG_NOT_TOUCH_MODAL:表示系統(tǒng)會將當(dāng)前Window區(qū)域以外的單擊事件傳遞給底層的Window延柠,而區(qū)域以內(nèi)的單擊事件則自己處理祸挪。一般都需要開啟此標(biāo)記,否則其他Window將無法收到單擊事件贞间。
- FLAG_SHOW_WHEN_LOCKED:表示W(wǎng)indow可顯示在鎖屏界面贿条。
-
type:表示W(wǎng)indow的類型。Window有三種類型:
- 應(yīng)用Window:對應(yīng)一個Activity增热。
- 子Window:不能單獨存在整以,需附屬特定的父Window。如Dialog钓葫。
- 系統(tǒng)Window: 需申明權(quán)限才能創(chuàng)建悄蕾。如Toast。
- Window是分層的,見下表帆调。
- 層級大的會覆蓋在層級小的Window上面奠骄。
- 對應(yīng)WindowManager.LayoutParams的type參數(shù)。
-
gravity:表示W(wǎng)indow的位置番刊。
- 默認是屏幕中間含鳞。
- x、y值相對于gravity芹务。
d.WindowManager&WindowManagerService:
Window的具體實現(xiàn)位于WindowManagerService中蝉绷。WindowManager和WindowManagerService的交互是一個IPC(跨進程通信)過程。
2.Window的內(nèi)部機制
- 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的具體實現(xiàn)類是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并沒有直接實現(xiàn)Window的三大操作桅狠,而是交給了WindowManagerGlobal。WindowManagerGlobal以單例模式向外提供自己的實例:
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
一幅圖說明這幾個類的關(guān)系:
因此轿秧,通過WindowManagerGlobal的addView()中跌、updateViewLayout()、removeView()實現(xiàn)WindowManager對Window的添加菇篡、刪除和修改漩符。
下面分別來看WindowManagerGlobal對Window操作的大致過程:
a.Window的添加過程:
b.Window的刪除過程
c.Window的更新過程
不難發(fā)現(xiàn), 以上驗證了之前的總結(jié):
- Windows的三大操作最終都會通過一個IPC過程移交給WindowManagerService驱还。
- Window和View通過ViewRootImpl來聯(lián)系嗜暴,ViewRootImpl可控制View的測量、布局和重繪铝侵。
推薦閱讀:源碼剖析之------Window的內(nèi)部實現(xiàn)機制灼伤、我眼中的Window創(chuàng)建/添加/刪除/更新過程
3.Window的創(chuàng)建過程
由于View必須依附Window才能呈現(xiàn)出來,因此有View的地方必有Window咪鲜。在Android中可以提供View的地方有Activity、Dialog和Toast撞鹉,下面分別來看以上三種Window的大致創(chuàng)建過程:
a.Activity的Window創(chuàng)建過程
推薦閱讀:Activity的Window創(chuàng)建過程分析(源碼)
b.Dialog的Window創(chuàng)建過程
Step1:創(chuàng)建WindowDialog疟丙。和Activity類似,同樣是通過PolicyManager.makeNewWindow()來實現(xiàn)鸟雏。
Step2:初始化DecorView并將Dialog的視圖添加到DecorView中去享郊。和Activity類似,同樣是通過Window.setContentView()來實現(xiàn)孝鹊。
Step3:將DecorView添加到Window中顯示炊琉。和Activity一樣,都是在自身要出現(xiàn)在前臺時才會將添加Window。
- Dialog.show()方法:完成DecorView的顯示苔咪。
- WindowManager.remoteViewImmediate()方法:當(dāng)Dialog被dismiss時移除DecorView锰悼。
c.Toast的Window創(chuàng)建過程
①Toast的內(nèi)部的視圖由兩種方式指定:
- 系統(tǒng)默認的樣式;
- 通過setView()指定一個自定義View团赏。
②Toast具有定時取消功能箕般,故系統(tǒng)采用Handler做定時處理。
③在Toast內(nèi)部有兩類IPC過程:
- Toast訪問NotificationManagerService(NMS)舔清;
- NotificationManagerService回調(diào)Toast里的TN接口丝里。
④Toast提供方法show()和cancel()分別用于顯示和隱藏Toast。
- Toast的顯示和隱藏都需要通過NMS來實現(xiàn)体谒,由于NMS運行在系統(tǒng)進程中杯聚,故需通過遠程調(diào)用的方式來進行顯示和隱藏Toast。
- NMS處理Toast的顯示和隱藏請求時會跨進程回調(diào)TN中的方法抒痒,由于TN運行在Binder線程池中幌绍,故需通過Handler將其切換到當(dāng)前線程(發(fā)送Toast請求的線程)。
NMS只是起到了管理Toast隊列及其延時的效果评汰,Toast 的顯示和隱藏實際是通過TN來實現(xiàn)的纷捞。
推薦閱讀:Android對話框Dialog,PopupWindow被去,Toast的實現(xiàn)機制
希望這篇文章對你有幫助~