日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Android進階:深入理解Android窗口管理框架機制

[[423965]]

前言

WindowManagerService是位于Framework層的窗口管理服務,它的職責是管理系統(tǒng)中的所有窗口,也就是Window,關(guān)于Window的介紹,通俗來說,Window就是手機上一塊顯示區(qū)域,也就是Android中的繪制畫布Surface,添加一個Window的過程,也就是申請分配一塊Surface的過程,而整個流程的管理者正是WindowManagerService;

創(chuàng)新互聯(lián)建站專注于企業(yè)全網(wǎng)營銷推廣、網(wǎng)站重做改版、伊犁網(wǎng)站定制設計、自適應品牌網(wǎng)站建設、H5場景定制、商城系統(tǒng)網(wǎng)站開發(fā)、集團公司官網(wǎng)建設、外貿(mào)網(wǎng)站建設、高端網(wǎng)站制作、響應式網(wǎng)頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為伊犁等各大城市提供網(wǎng)站開發(fā)制作服務。

今天我們來分析下窗口WMS相關(guān)的知識點;

一、窗口相關(guān)概念

1、WindowManagerService概念

(1)WindowManagerService概念

Framework層的窗口管理服務,職責是管理Android系統(tǒng)中所有window。窗口管理服務,繼承IWindowManager.Stub,Binder服務端,因此WM與WMS的交互也是一個IPC過程。WMS主要做的事情如下:

  • Z-ordered的維護函數(shù)
  • 輸入法管理
  • AddWindow/RemoveWindow
  • Layerout
  • Token管理,AppToken
  • 活動窗口管理(FocusWindow)
  • 活動應用管理(FocusApp)
  • 轉(zhuǎn)場動畫
  • 系統(tǒng)消息收集線程
  • 系統(tǒng)消息分發(fā)線程

(2)WindowManager

應用與窗口管理服務WindowManagerService交互的接口;

(3)PhoneWindowManager

實現(xiàn)了窗口的各種策略,定義了窗口相關(guān)策略,比如:告訴WMS某一個類型Window的Z-Order的值是多少,幫助WMS矯正不合理的窗口屬性,為WMS監(jiān)聽屏幕旋轉(zhuǎn)的狀態(tài),預處理一些系統(tǒng)按鍵事件;

(4)Choreographer

用戶控制窗口動畫、屏幕選擇等操作,它擁有從顯示子系統(tǒng)獲取Vsync同步事件的能力,從而可以在合適的時機通知渲染動作,避免在渲染的過程中因為發(fā)生屏幕重繪而導致的畫面撕裂。WMS使用Choreographer負責驅(qū)動所有的窗口動畫、屏幕旋轉(zhuǎn)動畫、墻紙動畫的渲染;

(5)DisplayContent

用于描述多屏輸出相關(guān)信息;

根據(jù)窗口的顯示位置將其分組。隸屬于同一個DisplayContent的窗口將會被顯示在同一個屏幕中。每個DisplayContent都對應著唯一ID,在添加窗口的時候可以通過指定這個ID決定其將顯示在哪個屏幕中;

DisplayContent是一個非常具有隔離性的一個概念。處于不同DisplayContent的兩個窗口在布局、顯示順序以及動畫處理上不會產(chǎn)生任何耦合;

(6)WindowState

描述窗口的狀態(tài)信息以及和WindowManagerService進行通信,一般一個窗口對應一個WindowState。它用來表示一個窗口的所有屬性;

(7)WindowToken

  • 窗口Token,用來做Binder通信;同時也是一種標識;
  • 在進行窗口Zorder排序時,屬于同一個WindowToken的窗口會被安排在一起,而且在其中定義的一些屬性將會影響所有屬于此WindowToken的窗口,這些都表明了屬于同一個WindowToken的窗口之間的緊密聯(lián)系;
  • 應用組件在需要新的窗口時,必須提供WindowToken以表明自己的身份,并且窗口的類型必須與所持有的WindowToken的類型一致;
  • 在創(chuàng)建系統(tǒng)類型的窗口時不需要提供一個有效的Token,WMS會隱式地為其聲明一個WindowToken,看起來誰都可以添加個系統(tǒng)級的窗口。難道Android為了內(nèi)部使用方便而置安全于不顧嗎?非也,addWindow()函數(shù)一開始的mPolicy.checkAddPermission()的目的就是如此。它要求客戶端必須擁有SYSTEM_ALERT_WINDOW或INTERNAL_SYSTEM_WINDOW權(quán)限才能創(chuàng)建系;

(8)Session

App進程通過建立Session代理對象和Session對象通信,進而和WMS建立連接;

(9)SurfaceFlinger

SurfaceFlinger負責管理Android系統(tǒng)的幀緩沖區(qū)(Frame Buffer),Android設備的顯示屏被抽象為一個幀緩沖區(qū),而Android系統(tǒng)中的SurfaceFlinger服務就是通過向這個幀緩沖區(qū)寫入內(nèi)容來繪制應用程序中的用戶界面的;

(10)InputManager

管理每個窗口的輸入事件通道(InputChannel)以及向通道上派發(fā)事件;

(11)Animator

所有窗口動畫的總管(WindowStateAnimator對象)。在Choreographer的驅(qū)動下,逐個渲染所有的動畫;

2、Window

  • 表示一個窗口的概念,是所有View的直接管理者,任何視圖都通過Window呈現(xiàn)(點擊事件由Window->DecorView->View;Activity的setContentView底層通過Window完成)
  • Window是一個抽象類,具體實現(xiàn)是PhoneWindow;
  • 創(chuàng)建Window需要通過WindowManager創(chuàng)建;
  • WindowManager是外界訪問Window的入口;
  • Window的具體實現(xiàn)位于WindowManagerService中;
  • WindowManager和WindowManagerService的交互是通過IPC進程間通信完成的;
  • 定義窗口樣式和行為的抽象基類,用于作為頂層的View加到WindowManager中,其實現(xiàn)類是PhoneWindow;
  • 每個Window都需要指定一個Type(應用窗口、子窗口、系統(tǒng)窗口)。Activity對應的窗口是應用窗口;PhoneWindow,ContextMenu,OptionMenu是常用的子窗口;像Toast和系統(tǒng)警告提示框(如ANR)就是系統(tǒng)窗口,還有很多應用的懸浮窗也屬于系統(tǒng)窗口;

3、Surface

  • 在Android中,一個窗口會獨占一個Surface,Surface其實就是一個畫布,應用程序通過Canvas或者OpenGL在Surface上繪制內(nèi)容;
  • 在Surface上繪制后,通過SurfaceFlinger將多塊Surface的內(nèi)容按照Z-order進行混合并輸出到FrameBuffer,從而將Android頁面展示給用戶;
  • 每個窗口都有一塊Surface用于顯示自己的ui,必然需要一個角色對窗口進行統(tǒng)一管理,這個時候,WMS應運而生。WMS為所有窗口分配Surface,掌管z-order以及位置、尺寸、窗口的進場出場動畫,并且還是輸入系統(tǒng)的中轉(zhuǎn)站;
  • 布局系統(tǒng):計算管理窗口的位置和層次;
  • 動畫系統(tǒng):根據(jù)布局系統(tǒng)的計算渲染窗口動畫;

4、Window的Type

  • 應用窗口:層級范圍是1~99
  • 子窗口:層級范圍是1000~1999
  • 系統(tǒng)窗口:層級范圍是2000~2999

5、窗口flags顯示屬性

 
 
 
 
  1. // 窗口特征標記 
  2. public int flags; 
  3. // 當該window對用戶可見時,允許鎖屏 
  4. public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001; 
  5. // 窗口后面的所有內(nèi)容都變暗 
  6. public static final int FLAG_DIM_BEHIND        = 0x00000002; 
  7. // 窗口后面的所有內(nèi)容都變模糊 
  8. public static final int FLAG_BLUR_BEHIND        = 0x00000004; 
  9. // 窗口不能獲得焦點 
  10. public static final int FLAG_NOT_FOCUSABLE      = 0x00000008; 
  11. // 窗口不接受觸摸屏事件 
  12. public static final int FLAG_NOT_TOUCHABLE      = 0x00000010; 
  13. // 即使在該window可獲得焦點情況下,允許該窗口之處的點擊事件傳遞到當前窗口后面的窗口去 
  14. public static final int FLAG_NOT_TOUCH_MODAL    = 0x00000020; 
  15. // 當手機處于睡眠狀態(tài),如果屏幕被按下,那么該window將第一個收到觸摸事件 
  16. public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040; 
  17. // 當該window對用戶可見時,屏幕處于常亮狀態(tài) 
  18. public static final int FLAG_KEEP_SCREEN_ON     = 0x00000080; 
  19. // 讓window占滿整個屏幕,不留任何邊界 
  20. public static final int FLAG_LAYOUT_IN_SCREEN   = 0x00000100; 
  21. // 允許窗口超出整個手機屏幕 
  22. public static final int FLAG_LAYOUT_NO_LIMITS   = 0x00000200; 
  23. // window全名顯示 
  24. public static final int FLAG_FULLSCREEN      = 0x00000400; 
  25. // 恢復window非全屏顯示 
  26. public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800; 
  27. // 開啟窗口抖動 
  28. public static final int FLAG_DITHER             = 0x00001000; 
  29. // 安全內(nèi)容窗口,該窗口顯示時不允許截屏 
  30. public static final int FLAG_SECURE             = 0x00002000; 
  31. // 一種特殊模式,在該模式下,布局參數(shù)用于在將表面合成到屏幕時執(zhí)行縮放。 
  32. public static final int FLAG_SCALED             = 0x00004000; 
  33. public static final int FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000; 
  34. public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000; 
  35. public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000; 
  36. // 接收單個特殊的MotionEvent,以應對窗口外發(fā)生的觸摸。  
  37. // 不會收到完整的向下/向上/向上手勢,而只會收到第一次向下的位置作為ACTION_OUTSIDE。 
  38. public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000; 
  39. // 鎖屏時顯示該窗口 
  40. public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000; 
  41. // 系統(tǒng)的墻紙顯示在該窗口之后 
  42. public static final int FLAG_SHOW_WALLPAPER = 0x00100000; 
  43. // 當window被顯示的時候,系統(tǒng)將把它當做一個用戶活動事件,以點亮手機屏幕 
  44. public static final int FLAG_TURN_SCREEN_ON = 0x00200000; 
  45. // 該窗口顯示,消失鍵盤 
  46. public static final int FLAG_DISMISS_KEYGUARD = 0x00400000; 
  47. // 當window在可以接受觸摸屏情況下,讓因在該window之外,而發(fā)送到后面的window的 
  48. // 觸摸屏可以支持split touch 
  49. public static final int FLAG_SPLIT_TOUCH = 0x00800000; 
  50. // 對該window進行硬件加速,該flag必須在activity或者dialog的content view之前進行設置 
  51. public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000; 
  52. // 讓該window占滿整個手機屏幕,不留任何邊界 
  53. public static final int FLAG_LAYOUT_IN_OVERSCAN = 0x02000000; 
  54. // 透明狀態(tài)欄 
  55. public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000; 
  56. // 透明導航欄 
  57. public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000; 

二、 Window的添加流程

 
 
 
 
  1. public final class WindowManagerGlobal { 
  2.      public void addView(View view, ViewGroup.LayoutParams params, 
  3.                 Display display, Window parentWindow) { 
  4.             //校驗參數(shù)的合法性 
  5.             ... 
  6.             //ViewRootImpl封裝了View與WindowManager的交互力促 
  7.             ViewRootImpl root; 
  8.             View panelParentView = null; 
  9.             synchronized (mLock) { 
  10.                 // Start watching for system property changes. 
  11.                 if (mSystemPropertyUpdater == null) { 
  12.                     mSystemPropertyUpdater = new Runnable() { 
  13.                         @Override public void run() { 
  14.                             synchronized (mLock) { 
  15.                                 for (int i = mRoots.size() - 1; i >= 0; --i) { 
  16.                                     mRoots.get(i).loadSystemProperties(); 
  17.                                 } 
  18.                             } 
  19.                         } 
  20.                     }; 
  21.                     SystemProperties.addChangeCallback(mSystemPropertyUpdater); 
  22.                 } 
  23.                 int index = findViewLocked(view, false); 
  24.                 if (index >= 0) { 
  25.                     if (mDyingViews.contains(view)) { 
  26.                         // Don't wait for MSG_DIE to make it's way through root's queue. 
  27.                         mRoots.get(index).doDie(); 
  28.                     } else { 
  29.                         throw new IllegalStateException("View " + view 
  30.                                 + " has already been added to the window manager."); 
  31.                     } 
  32.                     // The previous removeView() had not completed executing. Now it has. 
  33.                 } 
  34.                 // If this is a panel window, then find the window it is being 
  35.                 // attached to for future reference. 
  36.                 if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && 
  37.                         wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 
  38.                     final int count = mViews.size(); 
  39.                     for (int i = 0; i < count; i++) { 
  40.                         if (mRoots.get(i).mWindow.asBinder() == wparams.token) { 
  41.                             panelParentView = mViews.get(i); 
  42.                         } 
  43.                     } 
  44.                 } 
  45.                 //通過上下文構(gòu)建ViewRootImpl 
  46.                 root = new ViewRootImpl(view.getContext(), display); 
  47.                 view.setLayoutParams(wparams); 
  48.                 //mViews存儲著所有Window對應的View對象 
  49.                 mViews.add(view); 
  50.                 //mRoots存儲著所有Window對應的ViewRootImpl對象 
  51.                 mRoots.add(root); 
  52.                 //mParams存儲著所有Window對應的WindowManager.LayoutParams對象 
  53.                 mParams.add(wparams); 
  54.             } 
  55.             // do this last because it fires off messages to start doing things 
  56.             try { 
  57.                 //調(diào)用ViewRootImpl.setView()方法完成Window的添加并更新界面 
  58.                 root.setView(view, wparams, panelParentView); 
  59.             } catch (RuntimeException e) { 
  60.                 // BadTokenException or InvalidDisplayException, clean up. 
  61.                 synchronized (mLock) { 
  62.                     final int index = findViewLocked(view, false); 
  63.                     if (index >= 0) { 
  64.                         removeViewLocked(index, true); 
  65.                     } 
  66.                 } 
  67.                 throw e; 
  68.             } 
  69.         } 

在這個方法里有三個重要的成員變量:

  • mViews 存儲著所有Window對應的View對象;
  • mRoots 存儲著所有Window對應的ViewRootImpl對象;
  • mParams 存儲著所有Window對應的WindowManager.LayoutParams對象;
  • 這里面提到了一個我們不是很熟悉的類ViewRootImpl,它其實就是一個封裝類,封裝了View與WindowManager的交互方式,它是View與WindowManagerService通信的橋梁;
  • 最后也是調(diào)用ViewRootImpl.setView()方法完成Window的添加并更新界面;

我們來看看這個方法的實現(xiàn)

 
 
 
 
  1. public final class ViewRootImpl implements ViewParent, 
  2.         View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks { 
  3.      public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { 
  4.             synchronized (this) { 
  5.                 if (mView == null) { 
  6.                     mView = view; 
  7.                     //參數(shù)校驗與預處理 
  8.                     ... 
  9.                     // Schedule the first layout -before- adding to the window 
  10.                     // manager, to make sure we do the relayout before receiving 
  11.                     // any other events from the system. 
  12.                     //1. 調(diào)用requestLayout()完成界面異步繪制的請求 
  13.                     requestLayout(); 
  14.                     if ((mWindowAttributes.inputFeatures 
  15.                             & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 
  16.                         mInputChannel = new InputChannel(); 
  17.                     } 
  18.                     mForceDecorViewVisibility = (mWindowAttributes.privateFlags 
  19.                             & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0; 
  20.                     try { 
  21.                         mOrigWindowType = mWindowAttributes.type; 
  22.                         mAttachInfo.mRecomputeGlobalAttributes = true; 
  23.                         collectViewAttributes(); 
  24.                         //2. 創(chuàng)建WindowSession并通過WindowSession請求WindowManagerService來完成Window添加的過程 
  25.                         //這是一個IPC的過程。 
  26.                         res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, 
  27.                                 getHostVisibility(), mDisplay.getDisplayId(), 
  28.                                 mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, 
  29.                                 mAttachInfo.mOutsets, mInputChannel); 
  30.                     } catch (RemoteException e) { 
  31.                         mAdded = false; 
  32.                         mView = null; 
  33.                         mAttachInfo.mRootView = null; 
  34.                         mInputChannel = null; 
  35.                         mFallbackEventHandler.setView(null); 
  36.                         unscheduleTraversals(); 
  37.                         setAccessibilityFocus(null, null); 
  38.                         throw new RuntimeException("Adding window failed", e); 
  39.                     } finally { 
  40.                         if (restore) { 
  41.                             attrs.restore(); 
  42.                         } 
  43.                     } 
  44.                     ... 
  45.             } 
  46.         }     
  • 調(diào)用requestLayout()完成界面異步繪制的請求,requestLayout()會去調(diào)用scheduleTraversals()來完成View的繪制,scheduleTraversals()方法將一個TraversalRunnable提交到工作隊列中執(zhí)行View的繪制。而TraversalRunnable最終調(diào)用了performTraversals()方法來完成實際的繪制操作。提到performTraversals()方法我們已經(jīng)很熟悉了;
  • 創(chuàng)建WindowSession并通過WindowSession請求WindowManagerService來完成Window添加的過程這是一個IPC的過程,WindowManagerService作為實際的窗口管理者,窗口的創(chuàng)建、刪除和更新都是由它來完成的,它同時還負責了窗口的層疊排序和大小計算等工作;

performTraversals()方法的實現(xiàn):

  • 獲取Surface對象,用于圖形繪制;
  • 調(diào)用performMeasure()方法測量視圖樹各個View的大小;
  • 調(diào)用performLayout()方法計算視圖樹各個View的位置,進行布局;
  • 調(diào)用performMeasure()方法對視圖樹的各個View進行繪制;

WindowManager與WindowManagerService的跨進程通信。Android的各種服務都是基于C/S結(jié)構(gòu)來設計的,系統(tǒng)層提供服務,應用層使用服務。WindowManager也是一樣,它與

WindowManagerService的通信是通過WindowSession來完成的;

首先調(diào)用ServiceManager.getService("window")獲取WindowManagerService,該方法返回的是IBinder對象,然后調(diào)用IWindowManager.Stub.asInterface()方法將WindowManagerService轉(zhuǎn)換為一個IWindowManager對象;

然后調(diào)用openSession()方法與WindowManagerService建立一個通信會話,方便后續(xù)的跨進程通信。這個通信會話就是后面我們用到的WindowSession;

基本上所有的Android系統(tǒng)服務都是基于這種方式實現(xiàn)的,它是一種基于AIDL實現(xiàn)的IPC的過程;

 
 
 
 
  1. public final class WindowManagerGlobal { 
  2.     public static IWindowSession getWindowSession() { 
  3.         synchronized (WindowManagerGlobal.class) { 
  4.             if (sWindowSession == null) { 
  5.                 try { 
  6.                     InputMethodManager imm = InputMethodManager.getInstance(); 
  7.                     //獲取WindowManagerService對象,并將它轉(zhuǎn)換為IWindowManager類型 
  8.                     IWindowManager windowManager = getWindowManagerService(); 
  9.                     //調(diào)用openSession()方法與WindowManagerService建立一個通信會話,方便后續(xù)的 
  10.                     //跨進程通信。 
  11.                     sWindowSession = windowManager.openSession( 
  12.                             new IWindowSessionCallback.Stub() { 
  13.                                 @Override 
  14.                                 public void onAnimatorScaleChanged(float scale) { 
  15.                                     ValueAnimator.setDurationScale(scale); 
  16.                                 } 
  17.                             }, 
  18.                             imm.getClient(), imm.getInputContext()); 
  19.                 } catch (RemoteException e) { 
  20.                     throw e.rethrowFromSystemServer(); 
  21.                 } 
  22.             } 
  23.             return sWindowSession; 
  24.         } 
  25.     } 
  26.     public static IWindowManager getWindowManagerService() { 
  27.         synchronized (WindowManagerGlobal.class) { 
  28.             if (sWindowManagerService == null) { 
  29.                 //調(diào)用ServiceManager.getService("window")獲取WindowManagerService,該方法返回的是IBinder對象 
  30.                 //,然后調(diào)用IWindowManager.Stub.asInterface()方法將WindowManagerService轉(zhuǎn)換為一個IWindowManager對象 
  31.                 sWindowManagerService = IWindowManager.Stub.asInterface( 
  32.                         ServiceManager.getService("window")); 
  33.                 try { 
  34.                     if (sWindowManagerService != null) { 
  35.                         ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale()); 
  36.                     } 
  37.                 } catch (RemoteException e) { 
  38.                     throw e.rethrowFromSystemServer(); 
  39.                 } 
  40.             } 
  41.             return sWindowManagerService; 
  42.         } 
  43.     } 
  44.  } 

三、 Window的刪除流程

Window的刪除流程也是在WindowManagerGlobal里完成

 
 
 
 
  1. public final class WindowManagerGlobal { 
  2.    public void removeView(View view, boolean immediate) { 
  3.         if (view == null) { 
  4.             throw new IllegalArgumentException("view must not be null"); 
  5.         } 
  6.         synchronized (mLock) { 
  7.             //1. 查找待刪除View的索引 
  8.             int index = findViewLocked(view, true); 
  9.             View curView = mRoots.get(index).getView(); 
  10.             //2. 調(diào)用removeViewLocked()完成View的刪除, removeViewLocked()方法 
  11.             //繼續(xù)調(diào)用ViewRootImpl.die()方法來完成View的刪除。 
  12.             removeViewLocked(index, immediate); 
  13.             if (curView == view) { 
  14.                 return; 
  15.             } 
  16.             throw new IllegalStateException("Calling with view " + view 
  17.                     + " but the ViewAncestor is attached to " + curView); 
  18.         } 
  19.     } 
  20.     private void removeViewLocked(int index, boolean immediate) { 
  21.         ViewRootImpl root = mRoots.get(index); 
  22.         View view = root.getView(); 
  23.         if (view != null) { 
  24.             InputMethodManager imm = InputMethodManager.getInstance(); 
  25.             if (imm != null) { 
  26.                 imm.windowDismissed(mViews.get(index).getWindowToken()); 
  27.             } 
  28.         } 
  29.         boolean deferred = root.die(immediate); 
  30.         if (view != null) { 
  31.             view.assignParent(null); 
  32.             if (deferred) { 
  33.                 mDyingViews.add(view); 
  34.             } 
  35.         } 
  36.     } 

我們再來看看ViewRootImpl.die()方法的實現(xiàn);

 
 
 
 
  1. public final class ViewRootImpl implements ViewParent, 
  2.         View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks { 
  3.       boolean die(boolean immediate) { 
  4.             // Make sure we do execute immediately if we are in the middle of a traversal or the damage 
  5.             // done by dispatchDetachedFromWindow will cause havoc on return. 
  6.             //根據(jù)immediate參數(shù)來判斷是執(zhí)行異步刪除還是同步刪除 
  7.             if (immediate && !mIsInTraversal) { 
  8.                 doDie(); 
  9.                 return false; 
  10.             } 
  11.             if (!mIsDrawing) { 
  12.                 destroyHardwareRenderer(); 
  13.             } else { 
  14.                 Log.e(mTag, "Attempting to destroy the window while drawing!\n" + 
  15.                         "  window=" + this + ", title=" + mWindowAttributes.getTitle()); 
  16.             } 
  17.             //如果是異步刪除,則發(fā)送一個刪除View的消息MSG_DIE就會直接返回 
  18.             mHandler.sendEmptyMessage(MSG_DIE); 
  19.             return true; 
  20.         } 
  21.         void doDie() { 
  22.             checkThread(); 
  23.             if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface); 
  24.             synchronized (this) { 
  25.                 if (mRemoved) { 
  26.                     return; 
  27.                 } 
  28.                 mRemoved = true; 
  29.                 if (mAdded) { 
  30.                     //調(diào)用dispatchDetachedFromWindow()完成View的刪除 
  31.                     dispatchDetachedFromWindow(); 
  32.                 } 
  33.                 if (mAdded && !mFirst) { 
  34.                     destroyHardwareRenderer(); 
  35.                     if (mView != null) { 
  36.                         int viewVisibility = mView.getVisibility(); 
  37.                         boolean viewVisibilityChanged = mViewVisibility != viewVisibility; 
  38.                   
    網(wǎng)頁名稱:Android進階:深入理解Android窗口管理框架機制
    文章地址:http://www.dlmjj.cn/article/ccopjeg.html