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);
}
}
}
如上所示:
1.QueuedInputEvent
是一种输入事件,链表结构,遍历传递给InputStage
2.InputStage
是处理输入的责任链,在调用deliver
时会遍历责任链传递事件
3.事件分发完成后会调用finishInputEvent
,告知SystemServer
进程的InputDispatcher
线程,最终将该事件移除,完成此次事件的分发消费。
那么问题来了,InputStage
的责任链是什么时候组件的呢?
[](()2.3 组装责任链
我们得回到ViewRootImpl.setView
方法中
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
…
// Set up the input pipeline.
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;
…
}
}
可以看到在setView
方法中,就把这条输入事件处理的责任链拼接完成了,不同的InputStage
子类,通过构造方法一个个串联起来了,那这些InputStage
到底干了啥呢?
-
SyntheticInputStage
。综合处理事件阶段,比如处理导航面板、操作杆等事件。 -
ViewPostImeInputStage
。视图输入处理阶段,比如按键、手指触摸等运动事件,我们熟知的view
事件分发就发生在这个阶段。 -
NativePostImeInputStage
。本地方法处理阶段,主要构建了可延迟的队列。 -
EarlyPostImeInputStage
。输入法早期处理阶段。 -
ImeInputStage
。输入法事件处理阶段,处理输入法字符。 -
ViewPreImeInputStage
。视图预处理输入法事件阶段,调用视图view
的dispatchKeyEventPreIme
方法。 -
NativePreImeInputStage
。本地方法预处理输入法事件阶段。
小结一下,事件到达应用端的主线程,会通过ViewRootImpl
进行一系列InputStage
来处理事件。这个阶段其实是对事件进行一些简单的分类处理,比如视图输入事件,输入法事件,导航面板事件等等。
我们的View
触摸事件就发生在ViewPostImeInputStage
阶段
final class ViewPostImeInputStage extends InputStage {
@Override
protected 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);
}
}
}
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
boolean handled = mView.dispatchPointerEvent(event)
return handled ? FINISH_HANDLED : FORWARD;
}
//View.java
public final boolean dispatchPointerEvent(MotionEvent event) {