新聞中心
[[423965]]
前言
WindowManagerService是位于Framework層的窗口管理服務(wù),它的職責(zé)是管理系統(tǒng)中的所有窗口,也就是Window,關(guān)于Window的介紹,通俗來(lái)說(shuō),Window就是手機(jī)上一塊顯示區(qū)域,也就是Android中的繪制畫布Surface,添加一個(gè)Window的過(guò)程,也就是申請(qǐng)分配一塊Surface的過(guò)程,而整個(gè)流程的管理者正是WindowManagerService;

創(chuàng)新互聯(lián)建站專注于企業(yè)全網(wǎng)營(yíng)銷推廣、網(wǎng)站重做改版、伊犁網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場(chǎng)景定制、商城系統(tǒng)網(wǎng)站開(kāi)發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為伊犁等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
今天我們來(lái)分析下窗口WMS相關(guān)的知識(shí)點(diǎn);
一、窗口相關(guān)概念
1、WindowManagerService概念
(1)WindowManagerService概念
Framework層的窗口管理服務(wù),職責(zé)是管理Android系統(tǒng)中所有window。窗口管理服務(wù),繼承IWindowManager.Stub,Binder服務(wù)端,因此WM與WMS的交互也是一個(gè)IPC過(guò)程。WMS主要做的事情如下:
- Z-ordered的維護(hù)函數(shù)
- 輸入法管理
- AddWindow/RemoveWindow
- Layerout
- Token管理,AppToken
- 活動(dòng)窗口管理(FocusWindow)
- 活動(dòng)應(yīng)用管理(FocusApp)
- 轉(zhuǎn)場(chǎng)動(dòng)畫
- 系統(tǒng)消息收集線程
- 系統(tǒng)消息分發(fā)線程
(2)WindowManager
應(yīng)用與窗口管理服務(wù)WindowManagerService交互的接口;
(3)PhoneWindowManager
實(shí)現(xiàn)了窗口的各種策略,定義了窗口相關(guān)策略,比如:告訴WMS某一個(gè)類型Window的Z-Order的值是多少,幫助WMS矯正不合理的窗口屬性,為WMS監(jiān)聽(tīng)屏幕旋轉(zhuǎn)的狀態(tài),預(yù)處理一些系統(tǒng)按鍵事件;
(4)Choreographer
用戶控制窗口動(dòng)畫、屏幕選擇等操作,它擁有從顯示子系統(tǒng)獲取Vsync同步事件的能力,從而可以在合適的時(shí)機(jī)通知渲染動(dòng)作,避免在渲染的過(guò)程中因?yàn)榘l(fā)生屏幕重繪而導(dǎo)致的畫面撕裂。WMS使用Choreographer負(fù)責(zé)驅(qū)動(dòng)所有的窗口動(dòng)畫、屏幕旋轉(zhuǎn)動(dòng)畫、墻紙動(dòng)畫的渲染;
(5)DisplayContent
用于描述多屏輸出相關(guān)信息;
根據(jù)窗口的顯示位置將其分組。隸屬于同一個(gè)DisplayContent的窗口將會(huì)被顯示在同一個(gè)屏幕中。每個(gè)DisplayContent都對(duì)應(yīng)著唯一ID,在添加窗口的時(shí)候可以通過(guò)指定這個(gè)ID決定其將顯示在哪個(gè)屏幕中;
DisplayContent是一個(gè)非常具有隔離性的一個(gè)概念。處于不同DisplayContent的兩個(gè)窗口在布局、顯示順序以及動(dòng)畫處理上不會(huì)產(chǎn)生任何耦合;
(6)WindowState
描述窗口的狀態(tài)信息以及和WindowManagerService進(jìn)行通信,一般一個(gè)窗口對(duì)應(yīng)一個(gè)WindowState。它用來(lái)表示一個(gè)窗口的所有屬性;
(7)WindowToken
- 窗口Token,用來(lái)做Binder通信;同時(shí)也是一種標(biāo)識(shí);
- 在進(jìn)行窗口Zorder排序時(shí),屬于同一個(gè)WindowToken的窗口會(huì)被安排在一起,而且在其中定義的一些屬性將會(huì)影響所有屬于此WindowToken的窗口,這些都表明了屬于同一個(gè)WindowToken的窗口之間的緊密聯(lián)系;
- 應(yīng)用組件在需要新的窗口時(shí),必須提供WindowToken以表明自己的身份,并且窗口的類型必須與所持有的WindowToken的類型一致;
- 在創(chuàng)建系統(tǒng)類型的窗口時(shí)不需要提供一個(gè)有效的Token,WMS會(huì)隱式地為其聲明一個(gè)WindowToken,看起來(lái)誰(shuí)都可以添加個(gè)系統(tǒng)級(jí)的窗口。難道Android為了內(nèi)部使用方便而置安全于不顧嗎?非也,addWindow()函數(shù)一開(kāi)始的mPolicy.checkAddPermission()的目的就是如此。它要求客戶端必須擁有SYSTEM_ALERT_WINDOW或INTERNAL_SYSTEM_WINDOW權(quán)限才能創(chuàng)建系;
(8)Session
App進(jìn)程通過(guò)建立Session代理對(duì)象和Session對(duì)象通信,進(jìn)而和WMS建立連接;
(9)SurfaceFlinger
SurfaceFlinger負(fù)責(zé)管理Android系統(tǒng)的幀緩沖區(qū)(Frame Buffer),Android設(shè)備的顯示屏被抽象為一個(gè)幀緩沖區(qū),而Android系統(tǒng)中的SurfaceFlinger服務(wù)就是通過(guò)向這個(gè)幀緩沖區(qū)寫入內(nèi)容來(lái)繪制應(yīng)用程序中的用戶界面的;
(10)InputManager
管理每個(gè)窗口的輸入事件通道(InputChannel)以及向通道上派發(fā)事件;
(11)Animator
所有窗口動(dòng)畫的總管(WindowStateAnimator對(duì)象)。在Choreographer的驅(qū)動(dòng)下,逐個(gè)渲染所有的動(dòng)畫;
2、Window
- 表示一個(gè)窗口的概念,是所有View的直接管理者,任何視圖都通過(guò)Window呈現(xiàn)(點(diǎn)擊事件由Window->DecorView->View;Activity的setContentView底層通過(guò)Window完成)
- Window是一個(gè)抽象類,具體實(shí)現(xiàn)是PhoneWindow;
- 創(chuàng)建Window需要通過(guò)WindowManager創(chuàng)建;
- WindowManager是外界訪問(wèn)Window的入口;
- Window的具體實(shí)現(xiàn)位于WindowManagerService中;
- WindowManager和WindowManagerService的交互是通過(guò)IPC進(jìn)程間通信完成的;
- 定義窗口樣式和行為的抽象基類,用于作為頂層的View加到WindowManager中,其實(shí)現(xiàn)類是PhoneWindow;
- 每個(gè)Window都需要指定一個(gè)Type(應(yīng)用窗口、子窗口、系統(tǒng)窗口)。Activity對(duì)應(yīng)的窗口是應(yīng)用窗口;PhoneWindow,ContextMenu,OptionMenu是常用的子窗口;像Toast和系統(tǒng)警告提示框(如ANR)就是系統(tǒng)窗口,還有很多應(yīng)用的懸浮窗也屬于系統(tǒng)窗口;
3、Surface
- 在Android中,一個(gè)窗口會(huì)獨(dú)占一個(gè)Surface,Surface其實(shí)就是一個(gè)畫布,應(yīng)用程序通過(guò)Canvas或者OpenGL在Surface上繪制內(nèi)容;
- 在Surface上繪制后,通過(guò)SurfaceFlinger將多塊Surface的內(nèi)容按照Z(yǔ)-order進(jìn)行混合并輸出到FrameBuffer,從而將Android頁(yè)面展示給用戶;
- 每個(gè)窗口都有一塊Surface用于顯示自己的ui,必然需要一個(gè)角色對(duì)窗口進(jìn)行統(tǒng)一管理,這個(gè)時(shí)候,WMS應(yīng)運(yùn)而生。WMS為所有窗口分配Surface,掌管z-order以及位置、尺寸、窗口的進(jìn)場(chǎng)出場(chǎng)動(dòng)畫,并且還是輸入系統(tǒng)的中轉(zhuǎn)站;
- 布局系統(tǒng):計(jì)算管理窗口的位置和層次;
- 動(dòng)畫系統(tǒng):根據(jù)布局系統(tǒng)的計(jì)算渲染窗口動(dòng)畫;
4、Window的Type
- 應(yīng)用窗口:層級(jí)范圍是1~99
- 子窗口:層級(jí)范圍是1000~1999
- 系統(tǒng)窗口:層級(jí)范圍是2000~2999
5、窗口flags顯示屬性
- // 窗口特征標(biāo)記
- public int flags;
- // 當(dāng)該window對(duì)用戶可見(jiàn)時(shí),允許鎖屏
- public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001;
- // 窗口后面的所有內(nèi)容都變暗
- public static final int FLAG_DIM_BEHIND = 0x00000002;
- // 窗口后面的所有內(nèi)容都變模糊
- public static final int FLAG_BLUR_BEHIND = 0x00000004;
- // 窗口不能獲得焦點(diǎn)
- public static final int FLAG_NOT_FOCUSABLE = 0x00000008;
- // 窗口不接受觸摸屏事件
- public static final int FLAG_NOT_TOUCHABLE = 0x00000010;
- // 即使在該window可獲得焦點(diǎn)情況下,允許該窗口之處的點(diǎn)擊事件傳遞到當(dāng)前窗口后面的窗口去
- public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;
- // 當(dāng)手機(jī)處于睡眠狀態(tài),如果屏幕被按下,那么該window將第一個(gè)收到觸摸事件
- public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
- // 當(dāng)該window對(duì)用戶可見(jiàn)時(shí),屏幕處于常亮狀態(tài)
- public static final int FLAG_KEEP_SCREEN_ON = 0x00000080;
- // 讓window占滿整個(gè)屏幕,不留任何邊界
- public static final int FLAG_LAYOUT_IN_SCREEN = 0x00000100;
- // 允許窗口超出整個(gè)手機(jī)屏幕
- public static final int FLAG_LAYOUT_NO_LIMITS = 0x00000200;
- // window全名顯示
- public static final int FLAG_FULLSCREEN = 0x00000400;
- // 恢復(fù)window非全屏顯示
- public static final int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800;
- // 開(kāi)啟窗口抖動(dòng)
- public static final int FLAG_DITHER = 0x00001000;
- // 安全內(nèi)容窗口,該窗口顯示時(shí)不允許截屏
- public static final int FLAG_SECURE = 0x00002000;
- // 一種特殊模式,在該模式下,布局參數(shù)用于在將表面合成到屏幕時(shí)執(zhí)行縮放。
- public static final int FLAG_SCALED = 0x00004000;
- public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000;
- public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
- public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;
- // 接收單個(gè)特殊的MotionEvent,以應(yīng)對(duì)窗口外發(fā)生的觸摸。
- // 不會(huì)收到完整的向下/向上/向上手勢(shì),而只會(huì)收到第一次向下的位置作為ACTION_OUTSIDE。
- public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
- // 鎖屏?xí)r顯示該窗口
- public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
- // 系統(tǒng)的墻紙顯示在該窗口之后
- public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
- // 當(dāng)window被顯示的時(shí)候,系統(tǒng)將把它當(dāng)做一個(gè)用戶活動(dòng)事件,以點(diǎn)亮手機(jī)屏幕
- public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
- // 該窗口顯示,消失鍵盤
- public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
- // 當(dāng)window在可以接受觸摸屏情況下,讓因在該window之外,而發(fā)送到后面的window的
- // 觸摸屏可以支持split touch
- public static final int FLAG_SPLIT_TOUCH = 0x00800000;
- // 對(duì)該window進(jìn)行硬件加速,該flag必須在activity或者dialog的content view之前進(jìn)行設(shè)置
- public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000;
- // 讓該window占滿整個(gè)手機(jī)屏幕,不留任何邊界
- public static final int FLAG_LAYOUT_IN_OVERSCAN = 0x02000000;
- // 透明狀態(tài)欄
- public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
- // 透明導(dǎo)航欄
- public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
二、 Window的添加流程
- public final class WindowManagerGlobal {
- public void addView(View view, ViewGroup.LayoutParams params,
- Display display, Window parentWindow) {
- //校驗(yàn)參數(shù)的合法性
- ...
- //ViewRootImpl封裝了View與WindowManager的交互力促
- ViewRootImpl root;
- View panelParentView = null;
- synchronized (mLock) {
- // Start watching for system property changes.
- if (mSystemPropertyUpdater == null) {
- mSystemPropertyUpdater = new Runnable() {
- @Override public void run() {
- synchronized (mLock) {
- for (int i = mRoots.size() - 1; i >= 0; --i) {
- mRoots.get(i).loadSystemProperties();
- }
- }
- }
- };
- SystemProperties.addChangeCallback(mSystemPropertyUpdater);
- }
- int index = findViewLocked(view, false);
- if (index >= 0) {
- if (mDyingViews.contains(view)) {
- // Don't wait for MSG_DIE to make it's way through root's queue.
- mRoots.get(index).doDie();
- } else {
- throw new IllegalStateException("View " + view
- + " has already been added to the window manager.");
- }
- // The previous removeView() had not completed executing. Now it has.
- }
- // If this is a panel window, then find the window it is being
- // attached to for future reference.
- if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
- wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- final int count = mViews.size();
- for (int i = 0; i < count; i++) {
- if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
- panelParentView = mViews.get(i);
- }
- }
- }
- //通過(guò)上下文構(gòu)建ViewRootImpl
- root = new ViewRootImpl(view.getContext(), display);
- view.setLayoutParams(wparams);
- //mViews存儲(chǔ)著所有Window對(duì)應(yīng)的View對(duì)象
- mViews.add(view);
- //mRoots存儲(chǔ)著所有Window對(duì)應(yīng)的ViewRootImpl對(duì)象
- mRoots.add(root);
- //mParams存儲(chǔ)著所有Window對(duì)應(yīng)的WindowManager.LayoutParams對(duì)象
- mParams.add(wparams);
- }
- // do this last because it fires off messages to start doing things
- try {
- //調(diào)用ViewRootImpl.setView()方法完成Window的添加并更新界面
- root.setView(view, wparams, panelParentView);
- } catch (RuntimeException e) {
- // BadTokenException or InvalidDisplayException, clean up.
- synchronized (mLock) {
- final int index = findViewLocked(view, false);
- if (index >= 0) {
- removeViewLocked(index, true);
- }
- }
- throw e;
- }
- }
- }
在這個(gè)方法里有三個(gè)重要的成員變量:
- mViews 存儲(chǔ)著所有Window對(duì)應(yīng)的View對(duì)象;
- mRoots 存儲(chǔ)著所有Window對(duì)應(yīng)的ViewRootImpl對(duì)象;
- mParams 存儲(chǔ)著所有Window對(duì)應(yīng)的WindowManager.LayoutParams對(duì)象;
- 這里面提到了一個(gè)我們不是很熟悉的類ViewRootImpl,它其實(shí)就是一個(gè)封裝類,封裝了View與WindowManager的交互方式,它是View與WindowManagerService通信的橋梁;
- 最后也是調(diào)用ViewRootImpl.setView()方法完成Window的添加并更新界面;
我們來(lái)看看這個(gè)方法的實(shí)現(xiàn)
- public final class ViewRootImpl implements ViewParent,
- View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
- public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- mView = view;
- //參數(shù)校驗(yàn)與預(yù)處理
- ...
- // Schedule the first layout -before- adding to the window
- // manager, to make sure we do the relayout before receiving
- // any other events from the system.
- //1. 調(diào)用requestLayout()完成界面異步繪制的請(qǐng)求
- requestLayout();
- if ((mWindowAttributes.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- mInputChannel = new InputChannel();
- }
- mForceDecorViewVisibility = (mWindowAttributes.privateFlags
- & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
- try {
- mOrigWindowType = mWindowAttributes.type;
- mAttachInfo.mRecomputeGlobalAttributes = true;
- collectViewAttributes();
- //2. 創(chuàng)建WindowSession并通過(guò)WindowSession請(qǐng)求WindowManagerService來(lái)完成Window添加的過(guò)程
- //這是一個(gè)IPC的過(guò)程。
- res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(),
- mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
- mAttachInfo.mOutsets, mInputChannel);
- } catch (RemoteException e) {
- mAdded = false;
- mView = null;
- mAttachInfo.mRootView = null;
- mInputChannel = null;
- mFallbackEventHandler.setView(null);
- unscheduleTraversals();
- setAccessibilityFocus(null, null);
- throw new RuntimeException("Adding window failed", e);
- } finally {
- if (restore) {
- attrs.restore();
- }
- }
- ...
- }
- }
- }
- 調(diào)用requestLayout()完成界面異步繪制的請(qǐng)求,requestLayout()會(huì)去調(diào)用scheduleTraversals()來(lái)完成View的繪制,scheduleTraversals()方法將一個(gè)TraversalRunnable提交到工作隊(duì)列中執(zhí)行View的繪制。而TraversalRunnable最終調(diào)用了performTraversals()方法來(lái)完成實(shí)際的繪制操作。提到performTraversals()方法我們已經(jīng)很熟悉了;
- 創(chuàng)建WindowSession并通過(guò)WindowSession請(qǐng)求WindowManagerService來(lái)完成Window添加的過(guò)程這是一個(gè)IPC的過(guò)程,WindowManagerService作為實(shí)際的窗口管理者,窗口的創(chuàng)建、刪除和更新都是由它來(lái)完成的,它同時(shí)還負(fù)責(zé)了窗口的層疊排序和大小計(jì)算等工作;
performTraversals()方法的實(shí)現(xiàn):
- 獲取Surface對(duì)象,用于圖形繪制;
- 調(diào)用performMeasure()方法測(cè)量視圖樹(shù)各個(gè)View的大小;
- 調(diào)用performLayout()方法計(jì)算視圖樹(shù)各個(gè)View的位置,進(jìn)行布局;
- 調(diào)用performMeasure()方法對(duì)視圖樹(shù)的各個(gè)View進(jìn)行繪制;
WindowManager與WindowManagerService的跨進(jìn)程通信。Android的各種服務(wù)都是基于C/S結(jié)構(gòu)來(lái)設(shè)計(jì)的,系統(tǒng)層提供服務(wù),應(yīng)用層使用服務(wù)。WindowManager也是一樣,它與
WindowManagerService的通信是通過(guò)WindowSession來(lái)完成的;
首先調(diào)用ServiceManager.getService("window")獲取WindowManagerService,該方法返回的是IBinder對(duì)象,然后調(diào)用IWindowManager.Stub.asInterface()方法將WindowManagerService轉(zhuǎn)換為一個(gè)IWindowManager對(duì)象;
然后調(diào)用openSession()方法與WindowManagerService建立一個(gè)通信會(huì)話,方便后續(xù)的跨進(jìn)程通信。這個(gè)通信會(huì)話就是后面我們用到的WindowSession;
基本上所有的Android系統(tǒng)服務(wù)都是基于這種方式實(shí)現(xiàn)的,它是一種基于AIDL實(shí)現(xiàn)的IPC的過(guò)程;
- public final class WindowManagerGlobal {
- public static IWindowSession getWindowSession() {
- synchronized (WindowManagerGlobal.class) {
- if (sWindowSession == null) {
- try {
- InputMethodManager imm = InputMethodManager.getInstance();
- //獲取WindowManagerService對(duì)象,并將它轉(zhuǎn)換為IWindowManager類型
- IWindowManager windowManager = getWindowManagerService();
- //調(diào)用openSession()方法與WindowManagerService建立一個(gè)通信會(huì)話,方便后續(xù)的
- //跨進(jìn)程通信。
- sWindowSession = windowManager.openSession(
- new IWindowSessionCallback.Stub() {
- @Override
- public void onAnimatorScaleChanged(float scale) {
- ValueAnimator.setDurationScale(scale);
- }
- },
- imm.getClient(), imm.getInputContext());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- return sWindowSession;
- }
- }
- public static IWindowManager getWindowManagerService() {
- synchronized (WindowManagerGlobal.class) {
- if (sWindowManagerService == null) {
- //調(diào)用ServiceManager.getService("window")獲取WindowManagerService,該方法返回的是IBinder對(duì)象
- //,然后調(diào)用IWindowManager.Stub.asInterface()方法將WindowManagerService轉(zhuǎn)換為一個(gè)IWindowManager對(duì)象
- sWindowManagerService = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));
- try {
- if (sWindowManagerService != null) {
- ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- return sWindowManagerService;
- }
- }
- }
三、 Window的刪除流程
Window的刪除流程也是在WindowManagerGlobal里完成
- public final class WindowManagerGlobal {
- public void removeView(View view, boolean immediate) {
- if (view == null) {
- throw new IllegalArgumentException("view must not be null");
- }
- synchronized (mLock) {
- //1. 查找待刪除View的索引
- int index = findViewLocked(view, true);
- View curView = mRoots.get(index).getView();
- //2. 調(diào)用removeViewLocked()完成View的刪除, removeViewLocked()方法
- //繼續(xù)調(diào)用ViewRootImpl.die()方法來(lái)完成View的刪除。
- removeViewLocked(index, immediate);
- if (curView == view) {
- return;
- }
- throw new IllegalStateException("Calling with view " + view
- + " but the ViewAncestor is attached to " + curView);
- }
- }
- private void removeViewLocked(int index, boolean immediate) {
- ViewRootImpl root = mRoots.get(index);
- View view = root.getView();
- if (view != null) {
- InputMethodManager imm = InputMethodManager.getInstance();
- if (imm != null) {
- imm.windowDismissed(mViews.get(index).getWindowToken());
- }
- }
- boolean deferred = root.die(immediate);
- if (view != null) {
- view.assignParent(null);
- if (deferred) {
- mDyingViews.add(view);
- }
- }
- }
- }
我們?cè)賮?lái)看看ViewRootImpl.die()方法的實(shí)現(xiàn);
- public final class ViewRootImpl implements ViewParent,
- View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
- boolean die(boolean immediate) {
- // Make sure we do execute immediately if we are in the middle of a traversal or the damage
- // done by dispatchDetachedFromWindow will cause havoc on return.
- //根據(jù)immediate參數(shù)來(lái)判斷是執(zhí)行異步刪除還是同步刪除
- if (immediate && !mIsInTraversal) {
- doDie();
- return false;
- }
- if (!mIsDrawing) {
- destroyHardwareRenderer();
- } else {
- Log.e(mTag, "Attempting to destroy the window while drawing!\n" +
- " window=" + this + ", title=" + mWindowAttributes.getTitle());
- }
- //如果是異步刪除,則發(fā)送一個(gè)刪除View的消息MSG_DIE就會(huì)直接返回
- mHandler.sendEmptyMessage(MSG_DIE);
- return true;
- }
- void doDie() {
- checkThread();
- if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
- synchronized (this) {
- if (mRemoved) {
- return;
- }
- mRemoved = true;
- if (mAdded) {
- //調(diào)用dispatchDetachedFromWindow()完成View的刪除
- dispatchDetachedFromWindow();
- }
- if (mAdded && !mFirst) {
- destroyHardwareRenderer();
- if (mView != null) {
- int viewVisibility = mView.getVisibility();
- boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
當(dāng)前名稱:Android進(jìn)階:深入理解Android窗口管理框架機(jī)制
網(wǎng)站鏈接:http://www.5511xx.com/article/ccopjeg.html


咨詢
建站咨詢
