# Android 从问题出发探索KeyEvent分发流程(1) PhoneWindowManager是如何收到事件的
# Android 从问题出发探索KeyEvent分发流程(2) Activity是如何收到事件的
View的KeyListener相对于前两个过程要简单的多,不涉及那么多jni调用,我们继续跟随Activity收到KeyEvent向前走
Step 1 Activty调用window.superDispatchKeyEvent,将事件交给window(实现类PhoneWindow)
/base/core/java/com/android/internal/policy/PhoneWindow.java
public boolean dispatchKeyEvent(KeyEvent event) {
onUserInteraction();
// Let action bars open menus in response to the menu key prioritized over
// the window handling it
final int keyCode = event.getKeyCode();
if (keyCode == KeyEvent.KEYCODE_MENU &&
mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
return true;
}
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);
}
Step 2 PhoneWindow转发Decoriew,一路将事件交给View处理
/base/core/java/com/android/internal/policy/PhoneWindow.java
public boolean superDispatchKeyEvent(KeyEvent event) {
return mDecor.superDispatchKeyEvent(event);
}
/base/core/java/com/android/internal/policy/DecorView.java
public boolean superDispatchKeyEvent(KeyEvent event) {
if (super.dispatchKeyEvent(event)) {
return true;
}
return (getViewRootImpl() != null) && getViewRootImpl().dispatchUnhandledKeyEvent(event);
}
/base/core/java/android/view/ViewGroup.java
public boolean dispatchKeyEvent(KeyEvent event) {
if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
== (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
if (super.dispatchKeyEvent(event)) {
return true;
}
} else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
== PFLAG_HAS_BOUNDS) {
/// M : add log to help debugging
if (ViewDebugManager.DEBUG_KEY) {
Log.d(TAG, "dispatchKeyEvent to focus child event = " + event + ", mFocused = "
+ mFocused + ",this = " + this);
}
if (mFocused.dispatchKeyEvent(event)) {
return true;
}
}
return false;
}
Step 3 View校验keyListener是否为空和是否是enable状态,回调keyListener.onKey
public boolean dispatchKeyEvent(KeyEvent event) {
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
/// M : add log to help debugging
if (ViewDebugManager.DEBUG_KEY) {
ViewDebugManager.getInstance().debugEventHandled(this, event, li.toString());
}
return true;
}
return false;
}
从Activity到View的KeyListener被调用,这个过程到这里就结束了