先参考一下老罗同志的关于key事件的分发流程。http://blog.csdn.net/luoshengyang/article/details/6882903#comments
这里主要是写一下事件从native层上到Java层后,即到了InputQueue后的分发流程,以keyEvent为例。
InputQueue.java中
private static void dispatchKeyEvent(InputHandler inputHandler,
KeyEvent event, long finishedToken) {
FinishedCallback finishedCallback = FinishedCallback.obtain(finishedToken);
inputHandler.handleKey(event, finishedCallback);
}
这是从native层回调java层的,接着调用了Inputhander的handlKey。InputHandler是一个接口,主要是ViewRootImpl的mInputHandler变量实现了这个接口。
private final InputHandler mInputHandler = new InputHandler() {
public void handleKey(KeyEvent event, InputQueue.FinishedCallback finishedCallback) {
startInputEvent(finishedCallback);
dispatchKey(event, true);
}
然后dispatchKey通过消息机制,会调用deliverKeyEvent()处理。在此函数中,会分几部,IME(输入法)处理之前
dispatchKeyEventPreIme
,ime处理,ime处理之后的处理
deliverKeyEventPostIme
// Perform predispatching before the IME.
if (mView.dispatchKeyEventPreIme(event)) {
finishKeyEvent(event, sendDone, true);
return;
}
// Dispatch to the IME before propagating down the view hierarchy.
// The IME will eventually call back into handleFinishedEvent.
if (mLastWasImTarget) {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
int seq = enqueuePendingEvent(event, sendDone);
if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq="
+ seq + " event=" + event);
imm.dispatchKeyEvent(mView.getContext(), seq, event, mInputMethodCallback);
return;
}
}
// Not dispatching to IME, continue with post IME actions.
deliverKeyEventPostIme(event, sendDone);
此处会有一个mView,是View类型,其实是Decorview。如何看出它是Decorview?可以看出,mView是在setView被赋的值,setview会在WindowManagerImpl的addview中调用,并传入了view参数。WindowManagerImpl也即是WindowManager的一个实现。addView则是由PhoneWindowmanager的addStartingWindow函数的wm.addView调用的,将DecorView传入。
那谁又会调用addStartingWindow?看名字吧,简单缕一下调用关系: ActivityStack-->WMS.setAppStartingWindow-->policy.addStartingWindow-->PhoneWindowManager.addStartingWindow-->WindowManager(impl).addview-->ViewRootImpl.setview.
一般来说,会执行deliverKeyEventPostIme。
// Make sure the fallback event policy sees all keys that will be delivered to the
// view hierarchy.
mFallbackEventHandler.preDispatchKeyEvent(event);
// Deliver the key to the view hierarchy.
if (mView.dispatchKeyEvent(event)) {
finishKeyEvent(event, sendDone, true);
return;
}
mFallbackEventHandler ,其实是PhoneFallbackEventHandler类型。
事件会分发到DecorView的dispatchKeyEvent。
DecorView(PhoneWindow的内部类):
if (!isDestroyed()) {
final Callback cb = getCallback();
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
if (handled) {
return true;
}
}
mFeatureId为-1,所以会通过cb.dispatchkeyEvent。通过查看代码会发现,cb是Window的Callback接口,由activity和dialog实现。就以activity为例吧,即分发到Activity的dispatchKeyEvent。
public boolean dispatchKeyEvent(KeyEvent event) {
onUserInteraction();
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);
}
从activity出发,先分发到窗口Window(phonewindow),然后没有被消耗掉的话再去调用activity的KeyEvent.dispatch, 回调onKeyDown。
PhoneWindow:
public boolean superDispatchKeyEvent(KeyEvent event) {
return mDecor.superDispatchKeyEvent(event);
}
调用了DecorView的superDispatchKeyEvent
public boolean superDispatchKeyEvent(KeyEvent event) {
if (super.dispatchKeyEvent(event)) {
return true;
}
// Not handled by the view hierarchy, does the action bar want it
// to cancel out of something special?
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
final int action = event.getAction();
// Back cancels action modes first.
if (mActionMode != null) {
if (action == KeyEvent.ACTION_UP) {
mActionMode.finish();
}
return true;
}
先分发到父类的dispatchKeyEvent。即FrameLayout-->ViewGroup
public boolean dispatchKeyEvent(KeyEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onKeyEvent(event, 1);
}
if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
if (super.dispatchKeyEvent(event)) {
return true;
}
} else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
if (mFocused.dispatchKeyEvent(event)) {
return true;
}
}
同样也是,看看焦点问题,会调用super也就是View的dispatchKeyEvent。
public boolean dispatchKeyEvent(KeyEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onKeyEvent(event, 0);
}
// Give any attached key listener a first crack at the event.
//noinspection SimplifiableIfStatement
if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
return true;
}
if (event.dispatch(this, mAttachInfo != null
? mAttachInfo.mKeyDispatchState : null, this)) {
return true;
}
调用event.dispatch时,如果down事件,则执行boolean res = receiver.onKeyDown(mKeyCode, this);此处是View调用,所以就回调View的onKeyDown。如果是activity调用,则执行activity的onKeyDown.
如果在这分发的过程中,返回了true,则相当于事件被消费掉了,则activity的onKeydown将不会被调用了。