本文基于Android 12。
InputEvent经过inputflinger读取后,通过Inputchannel发送到Java层的InputEventReceiver对象,输入事件和View的状态强相关,事件发送需要确定当前的焦点App,焦点Window(View),事件接收者是谁,所以InputEventReceiver对象也在View的创建流程中被初始化,ViewRootImpl中通过InputChannel参数实例化WindowInputEventReceiver,其覆盖了父类InputEventReceiver的onInputEvent()方法。
一、WindowInputEventReceiver
// ViewRootImpl.java final class WindowInputEventReceiver extends InputEventReceiver {public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {super(inputChannel, looper);}@Overridepublic void onInputEvent(InputEvent event) {enqueueInputEvent(event, this, 0, true);}}
调用enqueueInputEvent方法。
// ViewRootImpl.java QueuedInputEvent mPendingInputEventHead;void enqueueInputEvent(InputEvent event,InputEventReceiver receiver, int flags, boolean processImmediately) {QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);QueuedInputEvent last = mPendingInputEventTail;if (last == null) {mPendingInputEventHead = q;mPendingInputEventTail = q;} else {last.mNext = q;mPendingInputEventTail = q;}mPendingInputEventCount += 1;doProcessInputEvents();}
enqueueInputEvent对事件通过mPendingInputEventHead变量维护一个事件队列,doProcessInputEvents()进行下一步处理。
// ViewRootImpl.java void doProcessInputEvents() {while (mPendingInputEventHead != null) {QueuedInputEvent q = mPendingInputEventHead;mPendingInputEventHead = q.mNext;if (mPendingInputEventHead == null) {mPendingInputEventTail = null;}q.mNext = null;deliverInputEvent(q);}}
doProcessInputEvents对mPendingInputEventHead队列中所有事件进行分发。
// ViewRootImpl.java private void deliverInputEvent(QueuedInputEvent q) {try {InputStage stage;if (q.shouldSendToSynthesizer()) {stage = mSyntheticInputStage;} else {stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;}if (stage != null) {handleWindowFocusChanged();stage.deliver(q);} else {finishInputEvent(q);}}}
将事件交给InputStage处理,InputStage是Android实现事件责任链的基类,deliver()方法中处理是否传递给下一个阶段:forward(),或者结束事件的传递:finish()。
二、InputState
// ViewRootImpl.java
abstract class InputStage { public final void deliver(QueuedInputEvent q) {if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {forward(q);} else if (shouldDropInputEvent(q)) {finish(q, false);} else {traceEvent(q, Trace.TRACE_TAG_VIEW);final int result;try {result = onProcess(q);} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}apply(q, result);}}
}
InputStage是一个抽象类,deliver方法中调用了onProcess(q),子类覆盖onProcess方法实现自己的操作逻辑。
在ViewRootImpl的setView方法中定义了InputState的责任链:
// ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {// Set up the input pipeline.CharSequence counterSuffix = attrs.getTitle();mSyntheticInputStage = new SyntheticInputStage();InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,"aq:native-post-ime:" + counterSuffix);InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);InputStage imeStage = new ImeInputStage(earlyPostImeStage,"aq:ime:" + counterSuffix);InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,"aq:native-pre-ime:" + counterSuffix);mFirstInputStage = nativePreImeStage;mFirstPostImeInputStage = earlyPostImeStage;
}
从实例化的顺序可知事件传递阶段的流程:
nativePreImeStage->viewPreImeStage->imeStage->earlyPostImeStage->nativePostImeStage->viewPostImeStage->mSyntheticInputStage
关于各个InputStage的官方说明:
InputState | Description |
---|---|
NativePreImeInputStage | Delivers pre-ime input events to a native activity. Does not support pointer events. |
ViewPreImeInputStage | Delivers pre-ime input events to the view hierarchy. Does not support pointer events. |
ImeInputStage | Delivers input events to the ime. Does not support pointer events. |
EarlyPostImeInputStage | Performs early processing of post-ime input events. |
NativePostImeInputStage | Delivers post-ime input events to a native activity. |
ViewPostImeInputStage | Delivers post-ime input events to the view hierarchy. |
SyntheticInputStage | Performs synthesis of new input events from unhandled input events. |
可参考文章:https://blog.csdn.net/vviccc/article/details/93377708
一般用户接触到最多的Activity和View属于ViewPostImeInputStage阶段。
三、ViewPostImeInputStage
// ViewRootImpl.java final class ViewPostImeInputStage extends InputStage {@Overrideprotected int onProcess(QueuedInputEvent q) {if (q.mEvent instanceof KeyEvent) {return processKeyEvent(q);} else {final int source = q.mEvent.getSource();if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {return processPointerEvent(q);} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {return processTrackballEvent(q);} else {return processGenericMotionEvent(q);}}}}
processKeyEvent处理KeyEvent,MotionEvent有两种情况,触屏操作的MotionEvent调用processPointerEvent处理,轨迹球操作的MotionEvent调用processTrackballEvent处理。
接着查看processPointerEvent方法:
// ViewRootImpl.java
private int processPointerEvent(QueuedInputEvent q) {final MotionEvent event = (MotionEvent)q.mEvent;boolean handled = mView.dispatchPointerEvent(event);maybeUpdatePointerIcon(event);maybeUpdateTooltip(event);return handled ? FINISH_HANDLED : FORWARD;
}
调用mView.dispatchPointerEvent(event)方法。
// View.java @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)public final boolean dispatchPointerEvent(MotionEvent event) {if (event.isTouchEvent()) {return dispatchTouchEvent(event);} else {return dispatchGenericMotionEvent(event);}}
终于到了熟悉的dispatchTouchEvent(event)方法。接下来就是熟悉onInterceptTouchEvent(),onTouchEvent()。