First, let's take a look at Comrade Luo's key event distribution process. Http://blog.csdn.net/luoshengyang/article/details/6882903#comments
Here we mainly write down the distribution process of events from the native layer to the Java layer, that is, after the inputqueue, taking keyevent as an example.
Inputqueue. Java
private static void dispatchKeyEvent(InputHandler inputHandler, KeyEvent event, long finishedToken) { FinishedCallback finishedCallback = FinishedCallback.obtain(finishedToken); inputHandler.handleKey(event, finishedCallback); }
This is the callback from the native layer to the Java layer, and then calls the handlkey of inputhander. Inputhandler is an interface, mainly implemented by the minputhandler variable of viewrootimpl.
private final InputHandler mInputHandler = new InputHandler() { public void handleKey(KeyEvent event, InputQueue.FinishedCallback finishedCallback) { startInputEvent(finishedCallback); dispatchKey(event, true); }
Then, dispatchkey uses the message mechanism to call deliverkeyevent () for processing. In this function, there will be several parts, before IME (input method) is processed
dispatchKeyEventPreIme
, Ime processing, ime processing
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);
Here there will be an mview, which is of the view type, which is actually a decorview. How can we see that it is decorview? It can be seen that mview is assigned a value in setview. setview is called in addview of windowmanagerimpl and the view parameter is passed in. Windowmanagerimpl is also an implementation of windowmanager. Addview is called by WM. addview of addstartingwindow function of phonewindowmanager, and decorview is passed in.
Who will call addstartingwindow? Let's take a look at the call relationship: activitystack --> WMS. setappstartingwindow --> Policy. addstartingwindow --> phonewindowmanager. addstartingwindow --> windowmanager (impl). addview --> viewrootimpl. setview.
Generally, deliverkeyeventpostime is executed.
// 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 is actually the phonefallbackeventhandler type.
Events are distributed to the dispatchkeyevent of decorview.
Decorview (internal class of 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 is-1, so CB. dispatchkeyevent is used. You can view the code and find that CB is the callback interface of window, which is implemented by activity and dialog. Take the activity as an example, that is, the dispatchkeyevent that is distributed to the activity.
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); }
Starting from the activity, it is first sent to the window (phonewindow), and then calls the activity's keyevent. Dispatch if it is not consumed, and calls back the onkeydown.
Phonewindow:
public boolean superDispatchKeyEvent(KeyEvent event) { return mDecor.superDispatchKeyEvent(event); }
The decorview superdispatchkeyevent is called.
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; }
Distribute it to the dispatchkeyevent of the parent class first. That is, 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; } }
Similarly, if you look at the focus issue, super, that is, view's dispatchkeyevent will be called.
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; }
When you call event. Dispatch, if the event is down, execute Boolean res = cycler. onkeydown (mkeycode, this); here is the view call, so the onkeydown of the view is called back. If it is called by activity, the onkeydown of the activity will be executed.
If true is returned during the distribution process, the event is consumed, and the onkeydown of the activity will not be called.