<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                原文出處——>[Android應用程序窗口(Activity)實現框架簡要介紹和學習計劃](http://blog.csdn.net/luoshengyang/article/details/8170307) 前面我們學習了SurfaceFlinger服務的實現原理。有了這個基礎之后,從本文開始,我們就可以分析Android系統在Java層的UI實現了。我們知道,在Android應用程序的四大組件中,只有Activity組件與UI相關,它描述的是應用程序窗口,因此,我們就通過它的UI實現來分析Android系統在Java層的UI實現。本文主要是對Activity組件的UI實現作簡要介紹以及制定學習計劃。 Activity組件的UI實現需要與WindowManagerService服務和SurfaceFlinger服務進行交互。從前面Android應用程序鍵盤(Keyboard)消息處理機制分析一文可以知道,Activity組件在啟動完成后,會通過一個類型為Session的Binder對象來請求WindowManagerService為它創建一個類型為WindowState的對象,用來描述它的窗口狀態。此外,從Android應用程序與SurfaceFlinger服務的關系概述和學習計劃這一系列的文章又可以知道,Android應用程序會通過一個類型為Client的Binder對象來請求SurfaceFlinger服務為它創建一個類型為Layer的對象,用來描述它的窗口數據。 從Android應用程序請求SurfaceFlinger服務創建Surface的過程分析一文又可以知道,SurfaceFlinger服務為Android應用程序創建一個類型為Layer的對象之后,會返回一個類型為SurfaceLayer的Binder對象給Android應用程序,這樣Android應用程序就可以通過這個Binder對象來請求SurfaceFlinger服務來分配圖形緩沖區。 綜合上述信息,我們就可以得到Activity組件與WindowManagerService服務和SurfaceFlinger服務的交互模型,如圖1所示: :-: ![](https://box.kancloud.cn/30c4e74ca572e22d2627aacb2328bb1c_563x568.jpg) 圖1 Activity組件與WindowManagerService服務和SurfaceFlinger服務的交互模型 事實上,用來關聯Activity組件和Layer對象的SurfaceLayer對象并不是由Android應用程序請求SurfaceFlinger服務來創建的,而是由WindowManagerService服務請求SurfaceFlinger服務來創建的。WindowManagerService服務得到這個SurfaceLayer對象之后,再將它的一個代理對象返回給在Android應用程序這一側的Activity組件。這樣,Activity組件和WindowManagerService服務就可以通過同一個SurfaceLayer對象來操作在SurfaceFlinger服務這一側的Layer對象,而操作Layer對象的目的就是為了修改Activity組件的UI。 在前面Android應用程序與SurfaceFlinger服務的關系概述和學習計劃和Android系統Surface機制的SurfaceFlinger服務簡要介紹和學習計劃這兩個系列的文章中,我們已經分析在SurfaceFlinger服務這一側的Layer類和SurfaceLayer類的實現了。在現在的這一系列文章中,我們主要分析在Android應用程序這一側的Activity組件與UI相關的類的實現,以及在WindowManagerService服務這一側的WindowState類的實現。 我們首先看Activity組件的實現,如圖2所示: :-: ![](https://box.kancloud.cn/ff524f8268449b2fcad438f245a8781e_949x476.jpg) 圖2 Activity組件的類關系圖 Activity類是從ContextThemeWrapper類繼承下來的,而ContextThemeWrapper類又是從ContextWrapper類繼承下來的,最后ContextWrapper類又繼承了Context類。 從前面Android應用程序啟動過程源代碼分析一文可以知道,Activity組件在啟動的過程中,系統會為它創建一個ContextImpl對象,用來描述它的運行上下文環境。這個ContextImpl對象首先是通過調用Acitivity類的成員函數attach傳遞到Activity組件內部,接著再依次通過調用父類ContextThemeWrapper和ContextWrapper的成員函數attachBaseContext來分別保存在它們的成員變量mBase中。因此,ContextThemeWrapper和ContextWrapper類的成員變量mBase指向的實際上是一個ContextImpl對象。 從前面Android應用程序啟動過程源代碼分析一文還可以知道,系統為一個正在啟動的Activity組件創建了一個ContextImpl對象之后,還會調用這個ContextImpl對象的成員函數setOuterContext來將正在啟動的Activity組件保存在其成員變量mOuterContext中。這樣,一個Activity組件就可以通過其父類ContextThemeWrapper或者ContextWrapper的成員變量mBase來訪問用來描述它的運行上下文環境的一個ContextImpl對象,同時,一個ContextImpl對象也可以通過它的成員變量mOuterContext來訪問它的宿主Activity組件。 Activity類還有另外一個類型為WindowManager的成員變量mWindowManager,它實際上指向的一個LocalWindowManager對象。LocalWindowManager類是用來管理應用程序窗口的,例如,用來維護應用程序窗口內部的視圖(View)。LocalWindowManager類有一個類型為WindowManager的成員變量mWindowManager,它實際上指向的是一個WindowManagerImpl對象。系統通過調用WindowManagerImpl類的靜態成員函數getDefault來獲得一個WindowManagerImpl對象,然后保存在LocalWindowManager類的成員變量mWindowManager中。這樣,LocalWindowManager類就可以通過WindowManagerImpl類來真正實現管理應用程序窗口的功能。 從上面的分析中,我們還看不出的一個Activity組件的窗口是如何描述的。為了弄清楚這個問題,我們繼續分析Activity類的另外一個成員變量mWindow,如圖3所示: :-: ![](https://box.kancloud.cn/255a2207bec2ec415cc2bbc33ac5f29d_596x582.jpg) 圖3 Window類的實現 Activity類的成員變量mWindow的類型為Window,它用來描述一個應用程序窗口。這樣,通過這個成員變量,每一個Activity組件就都會有一個對應的Window對象,即一個對應的應用程序窗口。 Window類有一個類型為Context的成員變量mContext。這個成員變量指向的是一個Activity對象。當系統為一個Activity組件創建一個對應的Window對象時,就會將這個Activity組件的Context接口保存在這個對應的Window對象的成員變量mContext中。這樣,一個Window對象就可以通過它的成員變量mContext來訪問它所描述的Activity組件的資源。 Window類還有一個類型為Window.Callback的成員變量mCallback。這個成員變量和成員變量mContext一樣,都是指向同一個Activity對象,因為Activity類是實現了Window.Callback接口的。當系統為一個Activity組件創建一個對應的Window對象時,就會將這個Activity組件所實現的Window.Callback接口通過Window類的成員函數setCallback保存在對應的Window對象的成員變量mCallback。這樣,一個Window對象就可以通過它的成員變量mCallback來將一些事件交給與它所對應的Activity組件來處理,例如,將接收的鍵盤事件交給對應的Activity組件來處理。 最后,Window類還有一個類型為WindowManager的成員變量mWindowManager。這個成員變量指向的是一個LocalWindowManager對象。前面提到,Activity組件的成員變量mWindowManager指向的也是一個LocalWindowManager對象。系統在啟動一個Activity組件的過程中,會通過Window類的成員函數setWindowManager來將保存在它的成員變量mWindowManager中的一個LocalWindowManager對象也保存在對應的Window對象的成員變量mWindowManager。這樣,一個Activity組件以及它所對應的Window對象就可以使用同一個LocalWindowManager對象來管理它們所描述的UI了。 事實上,Activity類的成員變量mWindow指向的并不是一個Window對象,而是一個PhoneWindow對象。也就是說,一個Activity組件的UI是使用一個PhoneWindow對象來描述的。 Activity類的成員變量mWindow所指向的一個PhoneWindow對象是通過調用PolicyManager類的靜態成員函數makeNewWindow來創建的。PolicyManager類的實現如圖4所示: :-: ![](https://box.kancloud.cn/0d8d272d39caf2b545df50bc365ab004_667x225.jpg) 圖4 PolicyManager類的實現 PolicyManager類有一個類型為IPolicy的靜態成員變量sPolicy,它實際指向的是一個Policy對象。Policy類實現了IPolicy接口的成員函數makeNewWindow,而PolicyManager類就是通過這個成員函數來為一個Activity組件創建一個PhoneWindow對象的。 PhoneWindow類繼承了Window類,因此,它的對象可以保存Activity類的成員變量mWindow中。PhoneWindow類的實現如圖5所示: :-: ![](https://box.kancloud.cn/f04dde05ea6e56c6f8d59f239a28ed6d_680x428.jpg) 圖5 PhoneWindow類的實現 PhoneWindow類有兩個重要的成員變量mDecor和mContentParent,它們的類型分別DecorView和ViewGroup。其中,成員變量mDecor是用描述自己的窗口視圖,而成員變量mContentParent用來描述視圖內容的父窗口。 DecorView類繼承了FrameLayout類,而FrameLayout類又繼承了ViewGroup類,最后ViewGroup類又繼承了View類。View類有一個成員函數draw,它是用來繪制應用程序窗口的UI的。DecorView類、FrameLayout類和ViewGroup類都重寫了父類的成員函數draw,這樣,它們就都可以定制自己的UI。 DecorView類所描述的應用程序窗口視圖是否需要重新繪制是由另外一個類ViewRoot來控制的。系統在啟動一個Activity組件的過程中,會為這個Activity組件創建一個ViewRoot對象,同時還會將前面為這個Activity組件所創建的一個PhoneWindow對象的成員變量mDecor所描述的一個視圖(DecorView)保存在這個ViewRoot對象的成員變量mView中。這樣,這個ViewRoot對象就可以通過調用它的成員變量mView的所描述的一個DecorView的成員函數draw來繪制一個Acitivity組件的UI了。ViewRoot類的作用是非常大的,它除了用來控制一個Acitivity組件的UI繪制之外,還負責接收Acitivity組件的IO輸入事件,例如,鍵盤事件,這一點可以參考前面Android應用程序鍵盤(Keyboard)消息處理機制分析一文。 ViewRoot類的實現如圖6所示: :-: ![](https://box.kancloud.cn/5ccb934e8cd134a8b2ab2a3126da9e05_818x575.jpg) 圖6 ViewRoot類的實現 ViewRoot類是從Handler類繼承下來的。從前面Android應用程序消息處理機制(Looper、Handler)分析一文可以知道,從Handler類繼承下來的子類可以調用父類的成員函數sendMessage來向指定的線程的消息隊列發送消息,以及在自己重寫的成員函數handleMessage中處理該消息。 ViewRoot類在兩種情況需要經常應用程序進程的主線程的消息隊列發送消息。 第一種情況是當ViewRoot類從系統輸入管理器InputManager接收到鍵盤、觸摸屏等輸入事件時,它就會把這些輸入事件封裝成一個消息,并且發送到應用程序進程的主線程的消息隊列中去進一步處理,這樣就可以保證鍵盤、觸摸屏等輸入事件可以在應用程序進程的主線程中進行處理。這一點可以參考前面Android應用程序鍵盤(Keyboard)消息處理機制分析一文。 第二種情況是當ViewRoot類需要重新繪制與它所關聯的一個Activity組件的UI時,它就會將這個繪制UI的操作封裝成一個消息,并且發送到應用程序進程的主線程的消息隊列中去進一步處理,這樣同樣可以保證繪制UI的操作可以在應用程序進程的主線程中執行。 每一個ViewRoot對象都有一個類型為View的成員變量mView,它指向了一個DecorView對象。這個DecorView對象是從哪里來的呢?前面提到,每一個Activity組件都有一個對應的ViewRoot對象以及一個對應的PhoneWindow對象,這個DecorView對象就是來自于這個對應的PhoneWindow對象的成員變量mDecor。也就是說,與同一個Activity組件對應的ViewRoot對象和PhoneWindow對象分別通過各自的成員變量mView和mDecor引用了共一個DecorView對象。 每一個ViewRoot對象都有一個類型為WindowManager.LayoutParams的成員變量mWindowAttributes,它指向了一個ViewGroup.LayoutParams對象,用來描述與該ViewRoot對象對應的一個Activity組件的UI布局信息。 從上面的描述就可以知道,每一個Activity組件都有一個對應的ViewRoot對象、View對象以及WindowManager.LayoutParams對象。這三個對象的對應關系是由WindowManagerImpl類來維護的。具體來說,就是由WindowManagerImpl類的成員變量mRoots、mViews和mParams所描述的三個數組來維護的。例如,假設一個應用程序進程運行有兩個Activity組件,那么WindowManagerImpl類的成員變量mRoots、mViews和mParams所描述的三個數組的大小就等于2,其中,mRoots[0]、mViews[0]和mParams[0]對應于第一個啟動的Activity組件,而mRoots[1]、mViews[1]和mParams[1]對應于第二個啟動的Activity組件。 每一個ViewRoot對象都有一個類型為Surface的成員變量mSurface,它指向了一個Java層的Surface對象。這個Java層的Surface對象通過它的成員變量mNativeSurface與一個C++層的Surface對象。這個C++層的Surface對象就是我們在Android應用程序與SurfaceFlinger服務的關系概述和學習計劃這一系列文章中所分析的Surface類的實例了。這個Surface類是用來在Android應用程序進程這一側描述應用程序窗口的。從前面Android應用程序請求SurfaceFlinger服務創建Surface的過程分析一文可以知道,在C++層中,每一個Surface對象都有一個對應的SurfaceControl對象。這個對應的SurfaceControl對象是用來設置應用程序窗口的屬性,例如,設置大小、位置等屬性。 但是,與ViewRoot類的成員變量mSurface所對應的在C++層的Surface對象并沒有一個對應的SurfaceControl對象,這是因為ViewRoot類并不需要設置應用程序窗口的屬性,它需要做的只是往應用程序窗口的圖形緩沖區填充UI數據,即它需要設置的只是應用程序窗口的紋理。應用程序窗口的紋理保存在Java層的Surface類的成員變量mCanvas所描述一個畫布(Canvas)中,即通過這個畫布可以訪問到應用程序窗口的圖形緩沖區。當ViewRoot類需要重新繪制與它對應的Activity組件的UI時,它就會調用它的成員函數draw來執行這個繪制的操作。ViewRoot類的成員函數draw首先通過獲得保存它的成員變量mSurface內部的一塊畫布,然后再將這個畫布傳遞給它的成員變量mView所描述的一個View對象的成員函數draw。View類的成員函數draw得到了這塊畫布之后,就可以隨心所欲地上面繪制應用程序窗口的紋理了。這些紋理的繪制工作是通過Skia圖形庫API來進行的。 那么,應用程序窗口的屬性是由誰來管理的呢?這是由WindowManagerService服務來管理的。前面提到,在Android應用程序這一側的Activity組件是由WindowManagerService服務來為它請求SurfaceFlinger服務創建一個Layer對象以及一個SurfaceLayer對象的。這個SurfaceLayer對象創建完成之后,WindowManagerService服務就會將它封裝在一個Java層的Surface對象中,以后就可以通過這個Java層的Surface對象來請求SurfaceFlinger服務設置一個對應的應用程序窗口的屬性。 由于Java層的Surface對象實現了Parcelable接口,因此,WindowManagerService服務在為一個Activity組件請求SurfaceFlinger服務創建一個Layer對象以及一個SurfaceLayer對象之后,就可以將得到的Java層的Surface對象跨進程地返回給該Activity組件。Activity組件得到這個Surface對象之后,再使用保存在里面的SurfaceLayer對象來初始化與它所對應的一個ViewRoot對象的成員變量mSurface所描述的一個Java層的Surface對象。 那么,WindowManagerService服務又是什么時候會為一個Activity組件請求SurfaceFlinger服務創建一個Layer對象以及一個SurfaceLayer對象呢?ViewRoot類有一個類型為IWindowSession的靜態成員變量sWindowSession,它指向的實際上是一個實現了IWindowSession接口的Binder對象。這個Binder對象的類型為Session,運行在WindowManagerService服務這一側。當一個Activity組件的UI第一次要被繪制之前,它所運行在的應用程序進程就會通過ViewRoot類的靜態成員變量sWindowSession來向WindowManagerService服務發送一個請求。WindowManagerService服務接收到這個請求之后,再請求SurfaceFlinger服務為這個Activity組件創建一個Layer對象以及一個SurfaceLayer對象。這樣,這個Activity組件的UI才能真正地繪制在屏幕中。 至此,我們就簡要分析完成了在Android應用程序這一側的Activity組件與UI相關的類的實現,接下來我們繼續分析在WindowManagerService服務這一側的WindowState類的實現。 WindowState類的實現如圖7所示: :-: ![](https://box.kancloud.cn/a8bc90c61cf288d4bdbb0dc9bbdea106_631x414.jpg) 圖7 WindowState類的實現 在Android應用程序這一側,每一個Activity組件在WindowManagerService服務這一側都有一個對應的WindowState對象,用來描述Activity組件的窗口狀態。WindowState類有兩個重要的成員變量mSession和mSurface,它們的類型分別為SurfaceSession和Surface。接下來,我們就描述這兩個成員變量的作用。 前面提到,Activity組件是在啟動完成之后,請求WindowManagerService服務為它創建一個WindowState對象的。創建完成這個WindowState對象之后,WindowManagerService服務再調用它的成員函數attach來為它附加一個SurfaceSession對象。WindowState類的成員函數attach又是通過調用它的成員變量mSession所描述的一個Session對象的成員函數windowAddedLocked來附加一個SurfaceSession對象的。 Session類有一個類型為SurfaceSession的成員變量mSurfaceSession。當WindowState類的成員函數attach調用Session類的成員函數windowAddedLocked來為一個WindowState對象附加一個SurfaceSession對象的時候,后者首先會檢查它的成員變量mSurfaceSession是否已經指向了一個SurfaceSession對象。如果如果指向了的話,那么Session類的成員函數windowAddedLocked就什么也不用做,否則的話,Session類的成員函數windowAddedLocked就會創建一個SurfaceSession對象,并且保存在它的成員變量mSurfaceSession中。 SurfaceSession類有一個類型為int的成員變量mClient,它保存的是一個C++層的SurfaceComposerClient對象的地址,即每一個Java層的SurfaceSession對象在C++層都有一個對應的SurfaceComposerClient對象。當一個SurfaceSession對象創建的時候,與它所關聯的SurfaceComposerClient對象也會同時被創建。從前面Android應用程序與SurfaceFlinger服務的連接過程分析一文可以知道,SurfaceComposerClient類用來描述Android應用程序進程與SurfaceFlinger服務之間的一個連接,即每一個與UI相關的Android應用程序進程都有一個SurfaceComposerClient對象。 讀者可能會覺得奇怪,既然SurfaceComposerClient是用來描述Android應用程序進程與SurfaceFlinger服務的連接的,那么為什么WindowManagerService服務會在內部創建SurfaceComposerClient對象呢?由于WindowManagerService需要請求SurfaceFlinger服務來設置Android應用程序窗口的屬性,例如,設置應用程序窗口的位置、大小等,因此,它就需要為每一個Android應用程序進程創建一個SurfaceComposerClient對象連接到SurfaceFlinger服務中去,以便可以和SurfaceFlinger服務進行通信。 從上面的描述我們就可以知道,在WindowManagerService服務中,每一個Android應用程序進程都對應有一個SurfaceComposerClient對象。由于每一個SurfaceComposerClient對象都關聯有一個SurfaceSession對象,因此,我們又可以推斷出每一個Android應用程序進程在WindowManagerService服務中都對應有一個SurfaceSession對象。由于每一個SurfaceSession對象所屬的Session對象是一個Binder本地對象,并且它的Binder代理對象是保存在Android應用程序進程這一側的ViewRoot類的靜態成員變量sWindowSession中,因此,我們又可以推斷出每一個Android應用程序進程在WindowManagerService服務都有一個對應的Session對象。綜合起來就是,每一個Android應用程序進程在WindowManagerService服務這一側對應有一個Session對象、一個SurfaceSession對象以及一個SurfaceComposerClient對象。由于每一個Android應用程序進程都可以運行若干個Activity組件,因此,我們又可以說,Activity組件與WindowServiceManager服務這一側的Session對象、SurfaceSession對象以及SurfaceComposerClient對象是多對一的關系。 介紹了WindowState類的成員變量mSession之后,我們接著介紹另外一個成員變量mSurface,它的類型為Surface,前面我們已經介紹過Surface類在Android應用程序進程這一側的作用了,接下來我們就介紹它在WindowManagerService這一側的作用。 前面提到,WindowManagerService服務會在內部為每一個應用程序窗口,即每一個Activity組件,創建一個SurfaceLayer對象,這個SurfaceLayer對象是封裝成一個Java層的Surface對象中的。在Java層的Surface類中,有一個類型為int的成員變量mSurfaceControl,它保存的是在C++層的一個SurfaceControl對象的地址值,即在WindowManagerService服務這一側,每一個Java層的Surface對象在 C++層都有一個對應的SurfaceControl對象。這里我們強調是在WindowManagerService服務這一側,是因為在前面提到,在Android應用程序這一側,每一個Activity組件所對應的Java層的Surface對象在C++層是沒有一個對應的SurfaceControl對象,而只是對應有一個C++層的Surface對象。通過C++層的SurfaceControl對象可以設置應用程序窗口的屬性,而通過C++層的Surface對象則可以設置應用程序窗口的圖形緩沖區,即設置應用程序窗口的紋理,因此,我們就可以知道應用程序窗口的屬性是由WindowManagerService服務來設置的,而應用程序窗口的紋理是由它所在的進程負責設置的。 至此,我們就簡要地介紹了Android應用程序窗口的實現框架了。上面所介紹的類及其交互關系可能會比較模糊,不易理解。不要緊,接下來我們會通過一系列的文章來弄清楚它們的來龍去脈: 1. Android應用程序窗口的運行上下文的創建過程,即創建ContextImpl的創建過程; 2. Android應用程序窗口的創建過程,即PhoneWindow的創建過程; 3. Android應用程序窗口的視圖的創建過程,即DecorView的創建過程; 4. Android應用程序窗口與WindowManagerService服務的連接過程,即WindowState的創建過程; 5. Android應用程序窗口與SurfaceFlinger服務的連接過程,即Surface的創建過程; 6. Android應用程序窗口的繪制過程,即Surface的渲染過程; 學習了這些文章,我們就可以掌握Android應用程序窗口的實現框架了。掌握了Android應用程序窗口的實現框架之后,我們就可以再進一步去詳細地學習Android應用程序窗口的渲染過程。敬請關注!
                  <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>

                              哎呀哎呀视频在线观看