在android里,我們都知道activity.但是一個activity跟一個Window是一個什么關系呢? 在activity.java中,我們可以看到兩個變量,分別是:
private Window mWindow;
private WindowManager mWindowManager;
這這個變量是在哪里賦值的呢?可以看到attach函數(shù),
mWindow = PolicyManager.makeNewWindow(this);
跟進去看一下,可以發(fā)現(xiàn)返回的時候一個PhoneWindow對象,PhoneWindow是Window類的派生類。
mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
仔細跟蹤下這段代碼中我們可以得到WindowManager對象,并且這個對象是在系統(tǒng)唯一的,這個對象同樣被賦值給PhoneWindow的成員變量。
我們在新建一個activity的時候,往往喜歡用如下的代碼來定義該activity的UI界面,那么這個具體的實現(xiàn)是怎么來實現(xiàn)的呢?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
我們跟蹤setContentView就知道了。可以發(fā)現(xiàn)activity其實把這個操作交給了自己的mWindow來完成,通過跟蹤PhoneWindow中的setContentView函數(shù)可以得出以下知識:
1,每一個PhoneWiondow中都有一個叫DecorView的對象,該對象是該PhoneWiondow的框架view,可以找到這么一段代碼:
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(FILL_PARENT, FILL_PARENT));
該layoutResource則是資源ID,通過往上翻代碼就可以找得到。
2,一個PhoneWiondow中都有一個叫FrameLayout的對象mContentParent,該對象是從上述layoutResource中的布局xml中獲得的,這也將是activity中所有用戶新增加view都會被包含在這個對象當中。
總體可以這樣大致說明:一個activity包含有一個PhoneWiondow對象,而所有的UI部件都是放在PhoneWiondow中。
ViewRoot這個類在android的UI結(jié)構(gòu)中扮演的是一個中間者的角色,連接的是PhoneWindow跟WindowManagerService.
WindowManagerService中我們知道它讀取android系統(tǒng)里所有事件,鍵盤事件,軌跡球事件等等,它怎么分發(fā)到各個activity的呢?就是通過這個ViewRoot。
在每個PhoneWindow創(chuàng)建的時候,系統(tǒng)都會向WindowManger中的一個保存View數(shù)組增加PhoneWindow的DecorView對象,WindowManger在保存好這個View對象的同時,也會新創(chuàng)建一個ViewRoot對象用來溝通WindowManagerService。
可以查看WindowManagerImpl跟ViewRoot中的代碼,同時ViewRoot中我們可以看到一個W類型,該類型派生自IWindow.stub可以知道這個可以被用來作遠程調(diào)用。
res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets);
IwindowSession則是WindowManagerService中的遠程調(diào)用接口,上述代碼也表明了每創(chuàng)建了一個PhoneWindow,也就創(chuàng)建了一個ViewRoot,并將在WindowManagerService注冊。
接下來簡單的看下KeyEvent的傳遞。在WindowManagerService中
focus.mClient.dispatchKey(event);
這個段代碼的mClient則就是ViewRoot中的W類型,通過遠程調(diào)用,可以看看ViewRoot的處理:
boolean handled = mView != null
? mView.dispatchKeyEventPreIme(event) : true;
mView則是PhoneWindow的DecorView對象,接下來怎么具體傳遞可以慢慢去跟了