1. 程式人生 > >window、view相關

window、view相關

set tex 文件 交互 val 區域 調用 ger XML

View、Window以及Activity主要是用於顯示並與用戶交互
window view activity surfaceView

三者間的關系:
在Activity中要設置View時,通常用的方法是:setContentView(id);
而實際在Activity類中用的是:getWindow().setContentView(id);
此即view是放到window上的,獲得window的方法是:activity.this.getWindow();
Activity實際上是繼承 Context類
window是在Activity的 attach() 方法中實例化的: window = new PhoneWindow(this, window);

attach 優先於 onCreate 調用
即:activity調用attach創建window(PhoneWindow)對象,在activity中調用setContentView()向window中添加view PhoneWindow
實際上是在PhoneWindow 中的setContentView()方法中向ViewGroup(root)中添加view

dialog Toast都是在window上顯示的

window代表一塊可繪制顯示的區域,系統給window提供可繪制圖形的surface對象,而不管如何繪制;
window是為了管理view,為每個view提供canvas,去繪制.

Activity相當於一個界面,可直接在Activity裏處理事件,Activity初始化時得到一個window對象,window用於管理view,view即實際顯示到界面上的圖形...

View繪制流程: view樹結構
onMeasure() --> onLayout() --> onDraw()
measure:測量組件大小 layout:確定組件在視圖中的位置 draw:根據位置和大小畫組件
視圖繪制的起點在ViewRootImpl類的performTraversals()方法,該方法完成的工作主要是:
根據之前的狀態,判定是否重新計算測試視圖大小(measure)、是否重新放置視圖位置(layout)和是否重新重繪視圖(draw)

setContentView流程
setContentView整個過程主要是把Activity的布局文件或者java的View添加至窗口裏,重點概括為:
創建一個DecorView的對象mDecor,該mDecor對象將作為整個應用窗口的根視圖。
依據Feature等style theme創建不同的窗口修飾布局文件,並且通過findViewById獲取Activity布局文件該存放的地方(窗口修飾布局文件中id為content的FrameLayout)。
將Activity的布局文件添加至id為content的FrameLayout內。
當setContentView設置顯示OK以後會回調Activity的onContentChanged方法。Activity的各種View的findViewById()方法等都可以放到該方法中,系統會幫忙回調。

ViewRoot是連接WindowManager與DecorView的紐帶,View的整個繪制流程的三大步(measure、layout、draw)都是通過ViewRoot完成的。
當Activity對象被創建完畢後,會將DecorView添加到Window中(Window是對窗口的抽象,DecorView是一個窗口的頂級容器View,其本質是一個FrameLayout),
同時會創建ViewRootImpl(ViewRoot的實現類)對象,並將ViewRootImpl與DecorView建立關聯。關於ViewRoot,我們只需要知道它是聯系GUI管理系統和GUI呈現系統的紐帶。
View的繪制流程從ViewRoot的performTraversals方法開始,經過measure、layout、draw三大過程完成對一個View的繪制工作。

peformTraversal方法內部會調用measure、layout、draw這三個方法,這三個方法內部又分別調用onMeasure、onLayout、onDraw方法。
ViewRoot對應於ViewRootImpl類,它是連接WindowManager和DecorView的紐帶,View的三大流程是通過VeiwRoot來完成的。在ActivityThread中,
當Activity對象被創建完畢後,會將DecorVeiw添加到Window中,同時會創建ViewRootImpl對象,並將ViewRootImpl對象和DecorView建立關聯。

Activity內部有個Window成員,它的實例為PhoneWindow,PhoneWindow有個內部類是DecorView,這個DecorView就是存放布局文件的,
裏面有TitleActionBar[TitleView(ActionBar的容器)]和我們setContentView傳入進去的layout布局文件

使用View的getMeasuredWidth()和getMeasuredHeight()方法來獲取View測量的寬高,
必須保證這兩個方法在onMeasure流程之後被調用才能返回有效值。
使用View的getWidth()和getHeight()方法來獲取View測量的寬高,必須保證這兩個方法在onLayout流程之後被調用才能返回有效值。

onDraw:
區分View動畫和ViewGroup布局動畫,前者指的是View自身的動畫,可以通過setAnimation添加,
後者是專門針對ViewGroup顯示內部子視圖時設置的動畫,可以在xml布局文件中對ViewGroup設置layoutAnimation屬性
(譬如對LinearLayout設置子View在顯示時出現逐行、隨機、下等顯示等不同動畫效果)。

invalidate和postInvalidate方法:
請求重新繪制視圖,調用draw
invalidate在主線程調用
postInvalidate是在非主線程調用

View的requestLayout方法:
requestLayout()方法會調用measure過程和layout過程,不會調用draw過程,也不會重新繪制任何View包括該調用者本身。


viewRoot DecorView
ViewRoot實際是一個Handler,ViewRoot建立主View與WindowsManger通訊的橋梁。ViewRoot在本質上一個Handler。
ViewRoot 對應於ViewRootImpl類,View的三大流程都是通過ViewRoot來完成的。在ActivityThread中,當Activity對象被創建完畢之後,
會將DecorView添加到Window中,同時會創建ViewRootImpl對象,並將ViewRootImpl對象和DecorView建立關聯。

DecorView作為頂級View,一般情況下它內部會包含一個豎直方向的LinearLayout,在這個LinearLayout裏面有上下兩個部分,
上面是標題欄,下面是內容欄。DecorView其實是一個Framglayout,View層的事件都先經過DecorView,然後才傳遞給我們的View。

Window: 表示一個窗口,不一定有屏幕那麽大,可以很大也可以很小;
它包含一個View tree和窗口的layout 參數。
View tree的root View可以通過getDecorView得到。還可以設置Window的Content View。

WindowManager並不是整個系統的窗口管理器,而是所在應用進程的窗口管理器。
系統全局的窗口管理器運行在SystemServer進程中,是一個Service。

每個窗口對應著一個Window對象,一個根View和一個ViewRoot對象。要想創建一個窗口,可以調用
WindowManager的addView方法,作為參數的view將作為在該窗口上顯示的根view

window裏顯示的東西是view(activity是邏輯上的東 西,增加了生命周期管理等. 裏面具體的東西也是view。
而且啟動activity的實現也是往window裏加view),往window裏加view,是通過調用 WindowManager(WindowManagerImpl).addView()來實現的。

在 addView裏,會為每個view創建一個viewRoot(這是邏輯上的東西,用來負責view的事件處理和邏輯處理,
並和 WindowsManagerService建立聯系),而在WindowManagerImpl裏,會維護viewRoot的數組。
最終會調用ViewRoot.setView(),在setView裏會顯示該view等。在setView的實現裏,會調用Session.add()來 addWindow,通過這個方法,
會將ViewRoot和WindowManagerService聯系起來(比如說分發事件等),並且這個方法裏會調 用PhoneWindowManager.prepareAddWindowLw()。


window、view相關