Github連接
本文梳理了Activity、View碉熄、Window桨武、ViewRoot、Surface锈津、AMS呀酸、WMS之間的關(guān)系,由于跳轉(zhuǎn)間的流程紛繁復(fù)雜琼梆,一旦陷入代碼細(xì)節(jié)就難以自拔性誉,下文中分析省略掉很多細(xì)節(jié),想了解的可以閱讀源碼或者閱讀相對(duì)應(yīng)的書籍茎杂。
概念定義
ContextImpl:Context實(shí)現(xiàn)類错览。
PhoneWindow:Window唯一實(shí)現(xiàn)類。Window是一個(gè)抽象概念煌往,是添加到WindowManager的根容器倾哺。
ViewRootImpl:ViewRootImpl是View的根,它控制了View的測(cè)量和繪制,同時(shí)持有WindowSession通過Binder與WMS通信羞海,同時(shí)持有IWindow作為WSM的回調(diào)接口闲勺,用于例如touch事件的回調(diào)。
WindowManagerImpl:WindowManager和ViewManager的實(shí)現(xiàn)類扣猫,通過WindowManagerGlobal與WMS通信。
DecorView:繼承FrameLayout翘地,是視圖樹的根布局申尤。
使用AS自帶的tools/layout inspector可以看出,整個(gè)DecorView包含了三部分:navigationBarBackground為導(dǎo)航欄衙耕,statusBarBackground為狀態(tài)欄昧穿,LinearLayout為當(dāng)中內(nèi)容部分,展開LinearLayout.FrameLayout橙喘,可以得到action_bar_container即actionbar或toolbar和content(R.id.content)即真正setContentView的目標(biāo)时鸵。
下文中但凡遇到抽象類/接口,都用實(shí)現(xiàn)類替代厅瞎,而 -> 符號(hào)代表由函數(shù)跳轉(zhuǎn)到另一函數(shù)饰潜。
從啟動(dòng)Activity說(shuō)起
第一個(gè)部分是啟動(dòng)Activity到創(chuàng)建出ViewRootImpl。
從ContextImpl開始和簸,省略掉AMS里相關(guān)跳轉(zhuǎn)到最后ActivityThread.performLaunchActivity -> Activity.attach中創(chuàng)建出PhoneWindow彭雾。
繼續(xù)下一步調(diào)用方法 ActivityThread.handleResumeActivity -> WindowManagerImpl.addView創(chuàng)建出ViewRootImpl。
ViewRootImpl的構(gòu)造方法內(nèi)創(chuàng)建了WindowSession(Binder)锁保,通過它與WindowManagerService進(jìn)行通信薯酝。
小結(jié):?jiǎn)?dòng)Activity會(huì)創(chuàng)建ViewRootImpl和PhoneWindow,建立起與WMS的連接爽柒。
與WMS通信
第二步是ViewRootImpl與WMS通信吴菠。
接上第一步中在ViewRootImpl構(gòu)造方法中通過WindowSession -> Binder.openSession構(gòu)造出WindowSession。
由第一步7中WindowManagerImpl.addView -> … ->WMS.relayoutWindow根據(jù)Window測(cè)量的大小相對(duì)應(yīng)創(chuàng)建出SurfaceControl浩村,通過SurfaceControl.getSurface將測(cè)量結(jié)果寫入outSurface內(nèi)做葵,此處的outSurface就是ViewRootImpl.mSurface,注意此處只有大小心墅,還未有指向native surface的指針mNativeObject蜂挪。
由第一步7中WindowManagerImpl.addView -> … ->WindowState.attch,創(chuàng)建出WindowToken用來(lái)標(biāo)識(shí)Window類型嗓化,如子窗體(1000-1999)棠涮,應(yīng)用窗體(1-99)和系統(tǒng)窗體(2000-2999)。再創(chuàng)建WindowState——WMS端的Window對(duì)象刺覆,它持有Session與WindowManager通信严肪,更重要的是調(diào)用Session.windowAddedLocked創(chuàng)建出SurfaceSession。
SurfaceSession構(gòu)造方法里調(diào)用了nativeCreate,從這里開始就是native的世界驳糯,不是本文重點(diǎn)篇梭,但簡(jiǎn)單概括一下流程是通過創(chuàng)建SurfaceComposerClient與SurfaceFlinger進(jìn)行交互,鎖定一塊共享內(nèi)存酝枢,通過writeParcel返回給ViewRootImpl.mSurface恬偷,同時(shí)擁有了native surface的地址。
小結(jié):當(dāng)Activity準(zhǔn)備顯示時(shí)帘睦,會(huì)測(cè)量Window和添加Window袍患,創(chuàng)建出WMS服務(wù)對(duì)應(yīng)的WindowState,Surface和native Surface竣付。
繪制
繪制四要素:bitmap(一塊內(nèi)存保存像素)诡延,canvas(畫布用于畫像素),paint(畫筆)古胆,path(畫的對(duì)象)肆良。
應(yīng)用無(wú)論是使用View/Canvas繪制(軟件繪制,Skia)逸绎,或者使用硬件加速繪制惹恃,最底層都是與Surface(OpenGL)進(jìn)行交互。
再回到Activity的生命周期onCreate棺牧,調(diào)用setContentView創(chuàng)建一個(gè)不可見的DecorView座舍,當(dāng)ActivityThread.handleResumeActivity -> Activity.makeVisible設(shè)置DecorView為可見。
其中繪制的起點(diǎn)是ViewRootImpl.performTraversals -> ViewRootImpl.performMeasure -> ViewRootImpl.performLayout - > ViewRootImpl.performDraw調(diào)用作為根視圖DecorView的measure陨帆,layout曲秉,draw方法來(lái)遍歷視圖樹。
值得一提的是FrameBuffer的知識(shí)點(diǎn)疲牵,開始繪制時(shí)承二,會(huì)調(diào)用Surface.lockCanvas,由SurfaceFlinger鎖定一塊共享內(nèi)存?zhèn)鬟f給Canvas纲爸,內(nèi)存共享的是設(shè)備顯存亥鸠,在上面繪制相當(dāng)于在屏幕上繪畫。繪制結(jié)束調(diào)用Surface.unlockCanvasAndPost识啦,從Suface上detach掉canvas负蚊,釋放Surface。
觸類旁通之SurfaceView
SurfaceView會(huì)創(chuàng)建一個(gè)Z軸靠下的新Window颓哮,通過挖洞(重疊區(qū)域變透明)使自己可見家妆。
觀察一下SurfaceView的內(nèi)部結(jié)構(gòu),似乎和ViewRootImpl差不多冕茅,同時(shí)持有IWindowSession伤极,Surface和MyWindow(同ViewRootImple.WindowSession)
relayoutWindow蛹找,addWindow,Surface一氣呵成哨坪,流程比較簡(jiǎn)單庸疾,注意一下SurfaceHolder,一般使用SurfaceView時(shí)候都是操作SurfaceHolder.Callback当编,它作為內(nèi)部類一開始就創(chuàng)建出來(lái)了届慈,而在native surface創(chuàng)建完畢之后調(diào)用SurfaceHolder.Callback.surfaceCreated。
總結(jié)
Activity啟動(dòng)時(shí)除了通過ViewRootImpl讀取各個(gè)參數(shù)確定Window的大小忿偷,位置等等金顿,通過WMS創(chuàng)建出相應(yīng)大小的Surface和一塊共享內(nèi)存,等待DecorView通過Canvas繪制畫面牵舱。
參考資料
Android 7.1.1 源碼
Android官方文檔
《Android開發(fā)藝術(shù)探索》
《深入理解Android 卷1》
其他優(yōu)秀的中英文文章