1. 程式人生 > >activity和view之間的關係。Android Activity 、 Window 、 View之間的關係。

activity和view之間的關係。Android Activity 、 Window 、 View之間的關係。

https://blog.csdn.net/haiyang497661292/article/details/78097775

一、簡述如何將Activity展現在手機上

Tips:

Activity本身是沒辦法處理顯示什麼控制元件(view)的,是通過PhoneWindow進行顯示的

換句話說:activity就是在造PhoneWindow,顯示的那些view都交給了PhoneWindow處理顯示

1、在Activity建立時呼叫attach方法:

2、attach方法中會呼叫PolicyManager.makeNewWindow()

實際工作的是IPolicy介面的makeNewWindow方法

①、其中建立了一個window(可以比喻為一個房子上造了一個窗戶):mWindow = PolicyManager.makeNewWindow(this);

②、在window這個類中,才呼叫了setContentView(),這是最終的呼叫

       在Activity的setContentView方法中,實際上是呼叫:getWindow().setContentView(view, params);

       這裡的getWindow()就是獲取到一個Window物件

Tips:

       為啥attch優先於onCreate呼叫,就是由於在attch方法中,會建立window,有了window才能呼叫setContentView

3、在IPolicy的實現類中建立了PhoneWindow:

①、由mWindow = PolicyManager.makeNewWindow(this);,

②、這裡的makeNewWindow(this);方法中,返回的是:return sPolicy.makeNewWindow(context);

③、這個sPolicy實際是一個介面,其實現類是Policy,其中只是建立了一個PhoneWindow

4、在PhoneWindow的setContentView中向ViewGroup(root)中添加了需要顯示的內容

①、PhoneWindow是繼承Window的

②、setContentView這個方法中,需要先判斷一個mContentParent是否為空,因為在預設進來的時候,什麼都沒建立呢

       此時需要建立:installDecor(),DecorView是最根上的顯示的

       可以通過adt中的的tools中有個hierarchyviewer.bat的工具,可以檢視手機的結構

③、DecorView:是繼承與FrameLayout的,作為parent存在,最初顯示的

④、下次再載入的時候,mContentParent就不為空了,會將其中的所有的view移除掉,然後在通過佈局填充器載入佈局

二、三者關係:

1、在Activity中呼叫attach,建立了一個Window

2、建立的window是其子類PhoneWindow,在attach中建立PhoneWindow

3、在Activity中呼叫setContentView(R.layout.xxx)

4、其中實際上是呼叫的getWindow().setContentView()

5、呼叫PhoneWindow中的setContentView方法

6、建立ParentView:

       作為ViewGroup的子類,實際是建立的DecorView(作為FramLayout的子類)

7、將指定的R.layout.xxx進行填充

通過佈局填充器進行填充【其中的parent指的就是DecorView】

8、呼叫到ViewGroup

9、呼叫ViewGroup的removeAllView(),先將所有的view移除掉

10、新增新的view:addView()

 

Tips:

       ①、Activity就是在造“窗戶”,即建立PhoneWindow

       ②、PhoneWindow才是進行顯示view的操作,主要就是setContentView()





setContentView整個過程主要是如何把Activity的佈局檔案或者java的View新增至窗口裡,重點概括為:

  1. 建立一個DecorView的物件mDecor,該mDecor物件將作為整個應用視窗的根檢視。

  2. 依據Feature等style theme建立不同的視窗修飾佈局檔案,並且通過findViewById獲取Activity佈局檔案該存放的地方(視窗修飾佈局檔案中id為content的FrameLayout)。

  3. 將Activity的佈局檔案新增至id為content的FrameLayout內。

  4. 當setContentView設定顯示OK以後會回撥Activity的onContentChanged方法。Activity的各種View的findViewById()方法等都可以放到該方法中,系統會幫忙回撥。



LayoutInflater的使用中重點關注inflate方法的引數含義:

  • inflate(xmlId, null); 只建立temp的View,然後直接返回temp。

  • inflate(xmlId, parent); 建立temp的View,然後執行root.addView(temp, params);最後返回root。

  • inflate(xmlId, parent, false); 建立temp的View,然後執行temp.setLayoutParams(params);然後再返回temp。

  • inflate(xmlId, parent, true); 建立temp的View,然後執行root.addView(temp, params);最後返回root。

  • inflate(xmlId, null, false); 只建立temp的View,然後直接返回temp。

  • inflate(xmlId, null, true); 只建立temp的View,然後直接返回temp。




1,如何理解ActivityViewWindow三者之間的關係?

這個問題真的很不好回答。所以這裡先來個算是比較恰當的比喻來形容下它們的關係吧。Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示檢視)LayoutInflater像剪刀,Xml配置像窗花圖紙。

1:Activity構造的時候會初始化一個Window,準確的說是PhoneWindow。

2:這個PhoneWindow有一個“ViewRoot”,這個“ViewRoot”是一個View或者說ViewGroup,是最初始的根檢視。

3:“ViewRoot”通過addView方法來一個個的新增View。比如TextView,Button等

4:這些View的事件監聽,是由WindowManagerService來接受訊息,並且回撥Activity函式。比如onClickListener,onKeyDown等。