}
......
}
......
}
這個函數定義在文件frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中。
PhoneWindow類的成員函數getCallback是從父類Window繼承下來的,它返回的是一個Window.Callback接口。每一個Activity組件都會實現一個Window.Callback接口,并且將這個Window.Callback接口設置到與它所關聯的一個PhoneWindow對象的內部去,這樣當該PhoneWindow對象接收到鍵盤事件的時候,就可以該鍵盤事件分發給與它所關聯的Activity組件處理。
DecorView類的成員變量mFeatureId用來描述當前正在處理的DecorView對象的特征,當它的值小于0的時候,就表示當前正在處理的一個DecorView對象是用來描述一個Activity組件窗口的頂層視圖的。
因此,當當前正在處理的DecorView對象描述的是一個Activity組件窗口的頂層視圖,并且這個Activity組件實現有一個Window.Callback接口時,DecorView類的成員函數dispatchKeyEvent就會調用該Window.Callback接口的成員函數dispatchKeyEvent來通知對應的Activity組件,它接收到一個鍵盤事件了。否則的話,參數event所描述的鍵盤事件就會被分發給當前正在處理的DecorView對象的父對象來處理,這是通過調用DecorView類的父類View的成員函數dispatchKeyEvent來實現的。
我們假設當前正在處理的DecorView對象描述的是一個Activity組件窗口的頂層視圖,并且這個Activity組件實現有一個Window.Callback接口,那么參數event所描述的鍵盤事件接下來就會分給該Activity組件處理。如果該Activity組件在處理完成這個鍵盤事件之后,希望該鍵盤事件還能繼續分發下去給其它對象處理,那么它所實現的Window.Callback接口的成員函數dispatchKeyEvent的返回值handled就會等于false,這時候DecorView類的成員函數dispatchKeyEvent就會將該鍵盤事件分發給與當前正在處理的DecorView對象所關聯的一個PhoneWindow對象的成員函數onKeyDown或者onKeyUp來處理,取決于變量isDown的值是true還是false,即當前發生的鍵盤事件是與按鍵按下有關,還是與按鍵松開有關。
PhoneWindow類的成員函數onKeyDown和onKeyUp主要是有來監控一些特殊按鍵事件,例如電話鍵和音量鍵,以便可以執行一些對應的邏輯。例如,當按下電話鍵時,就打開撥號程序;又如,當按下音量鍵時,就調節音量的大小。
接下來,我們就繼續分析Activity類所實現的Window.Callback接口的成員函數dispatchKeyEvent的實現,以便可以了解鍵盤事件在Activity組件窗口的分發過程。
Step 7. Activity.dispatchKeyEvent
[java] view plaincopyprint?
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks {
......
public boolean dispatchKeyEvent(KeyEvent event) {
......
Window win = getWindow();
if (win.superDispatchKeyEvent(event)) {
return true;
}
View decor = mDecor;
if (decor == null) decor = win.getDecorView();
return event.dispatch(this, decor != null
? decor.getKeyDispatcherState() : null, this);
}
......
}
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks {
......
public boolean dispatchKeyEvent(KeyEvent event) {
......
Window win = getWindow();
if (win.superDispatchKeyEvent(event)) {
return true;
}
View decor = mDecor;
if (decor == null) decor = win.getDecorView();
return event.dispatch(this, decor != null
? decor.getKeyDispatcherState() : null, this);
}
......
}
這個函數定義在文件frameworks/base/core/java/android/app/Activity.java中。
Activity類的成員函數getWindow返回的是與當前正處理的Activity組件所關聯的一個PhoneWindow對象,Activity類的成員函數dispatchKeyEvent獲得了這個PhoneWindow對象之后,就會調用它的成員函數superDispatchKeyEvent,以便可以將參數event所描述的鍵盤事件分發給它處理。
這個PhoneWindow對象在處理完成參數event所描述的鍵盤事件之后,如果希望該鍵盤事件能繼續往下分發,那么Activity類的成員函數dispatchKeyEvent就會將該鍵盤事件分發給當前正在處理的Activity組件處理,這是通過調用參數event所描述的一個KeyEvent對象的成員函數dispatch來實現的。
注意,在調用event所描述的一個KeyEvent對象的成員函數dispatch的時候,第一個參數指定為當前正在處理的Activity組件所實現的一個KeyEvent.Callback接口。參數event所指向的一個KeyEvent對象的成員函數dispatch的執行的過程中,就會相應地調用這個KeyEvent.Callback接口的成員函數onKeyDown、onKeyUp或者onKeyMultiple來處理它所描述的鍵盤事件,實際上就是調用Activity類的成員函數onKeyDown、onKeyUp或者onKeyMultiple來處理參數event所描述的鍵盤事件。因此,我們在自定義一個Activity組件時,如果需要處理分發給該Activity組件的鍵盤事件,那么就需要重寫父類Activity的成員函數onKeyDown、onKeyUp或者onKeyMultiple。
接下來,我們就繼續分析PhoneWindow類的成員函數superDispatchKeyEvent的實現,以便可以了解鍵盤事件在Activity組件窗口的分發過程。
原文轉自:http://blog.csdn.net/luoshengyang/article/details/8636153