<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 8.1 Window和WindowManager (1)`Window`是抽象類,具體實現是`PhoneWindow`,通過`WindowManager`就可以創建Window。WindowManager是外界訪問Window的入口,但是Window的具體實現是在`WindowManagerService`中,WindowManager和WindowManagerService的交互是一個IPC過程。所有的視圖例如Activity、Dialog、Toast都是附加在Window上的。 (2)通過WindowManager添加View的過程:將一個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);//0,0 分別是type和flags參數,在后面分別配置了 mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_SHOW_WHEN_LOCKED; mLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR; mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; mLayoutParams.x = 100; mLayoutParams.y = 300; mFloatingButton.setOnTouchListener(this); mWindowManager.addView(mFloatingButton, mLayoutParams); ~~~ flags參數解析: `FLAG_NOT_FOCUSABLE`:表示window不需要獲取焦點,也不需要接收各種輸入事件。此標記會同時啟用`FLAG_NOT_TOUCH_MODAL`,最終事件會直接傳遞給下層的具有焦點的window; `FLAG_NOT_TOUCH_MODAL`:在此模式下,系統會將window區域外的單擊事件傳遞給底層的window,當前window區域內的單擊事件則自己處理,一般都需要開啟這個標記; `FLAG_SHOW_WHEN_LOCKED`:開啟此模式可以讓Window顯示在鎖屏的界面上。?[奇怪的是我刪除這個標記還是在鎖屏看到了添加的組件orz] type參數表示window的類型,window共有三種類型:應用window,子window和系統window。應用window對應著一個Activity,子window不能獨立存在,需要附屬在特定的父window之上,比如Dialog就是子window。系統window是需要聲明權限才能創建的window,比如Toast和系統狀態欄這些都是系統window,需要聲明的權限是`<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />`。 (3)window是分層的,每個window都對應著`z-ordered`,層級大的會覆蓋在層級小的上面,應用window的層級范圍是`1~99`,子window的層級范圍是`1000~1999`,系統window的層級范圍是`2000~2999`。 [注意,應用window的層級范圍并不是`1~999`喲] (4)WindowManager繼承自`ViewManager`,常用的只有三個方法:`addView`、`updateView`和`removeView`。 ## 8.2 Window的內部機制 (1)Window是一個抽象的概念,不是實際存在的,它也是以View的形式存在。在實際使用中無法直接訪問Window,只能通過WindowManager才能訪問Window。每個Window都對應著一個View和一個`ViewRootImpl`,Window和View通過ViewRootImpl來建立聯系。 (2)Window的添加、刪除和更新過程都是IPC過程,以Window的添加為例,WindowManager的實現類對于`addView`、`updateView`和`removeView`方法都是委托給`WindowManagerGlobal`類,該類保存了很多數據列表,例如所有window對應的view集合`mViews`、所有window對應的ViewRootImpl的集合`mRoots`等,之后添加操作交給了ViewRootImpl來處理,接著會通過`WindowSession`來完成Window的添加過程,這個過程是一個IPC調用,因為最終是通過`WindowManagerService`來完成window的添加的。 ## 8.3 Window的創建過程 (1)Activity的window創建過程 1.Activity的啟動過程很復雜,最終會由`ActivityThread`中的`performLaunchActivity`來完成整個啟動過程,在這個方法內部會通過類加載器創建Activity的實例對象,并調用它的`attach`方法為其關聯運行過程中所依賴的一系列上下文環境變量; 2.Activity實現了Window的`Callback`接口,當window接收到外界的狀態變化時就會回調Activity的方法,例如`onAttachedToWindow`、`onDetachedFromWindow`、`dispatchTouchEvent`等; 3.Activity的Window是由`PolicyManager`來創建的,它的真正實現是`Policy`類,它會新建一個`PhoneWindow`對象,Activity的`setContentView`的實現是由`PhoneWindow`來實現的; 4.Activity的頂級View是`DecorView`,它本質上是一個`FrameLayout`。如果沒有DecorView,那么PhoneWindow會先創建一個DecorView,然后加載具體的布局文件并將view添加到DecorView的`mContentParent`中,最后就是回調Activity的`onContentChanged`通知Activity視圖已經發生了變化; 5.還有一個步驟是讓WindowManager能夠識別DecorView,在`ActivityThread`調用`handleResumeActivity`方法時,首先會調用Activity的onResume方法,然后會調用`makeVisible`方法,這個方法中DecorView真正地完成了添加和顯示過程。 ~~~ ViewManager vm = getWindowManager(); vm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; ~~~ (2)Dialog的Window創建過程 1.過程與Activity的Window創建過程類似,普通的Dialog的有一個特別之處,即它必須采用Activity的Context,如果采用Application的Context會報錯。原因是Application沒有`應用token`,應用token一般是Activity擁有的。[service貌似也有token?] (3)Toast的Window創建過程 1.Toast屬于系統Window,它內部的視圖由兩種方式指定:一種是系統默認的演示;另一種是通過`setView`方法來指定一個自定義的View。 2.Toast具有定時取消功能,所以系統采用了`Handler`。Toast的顯示和隱藏是IPC過程,都需要`NotificationManagerService`來實現。在Toast和NMS進行IPC過程時,NMS會跨進程回調Toast中的`TN`類中的方法,TN類是一個Binder類,運行在Binder線程池中,所以需要通過Handler將其切換到當前發送Toast請求所在的線程,所以Toast無法在沒有Looper的線程中彈出。 3.對于非系統應用來說,`mToastQueue`最多能同時存在`50`個`ToastRecord`,這樣做是為了防止`DOS`(Denial of Service,拒絕服務)。因為如果某個應用彈出太多的Toast會導致其他應用沒有機會彈出Toast。 其他學習資料 1.[Android應用開發之(WindowManager類使用)](http://blog.csdn.net/wang_shaner/article/details/8596380)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看