Link:
Android Input (1) -- InputManagerService启动
Android Input (2) -- inputReader
Android Input (3) -- inputDispatcher
Android Input (4) -- inputDispatcher到ViewRootImpl
Android Input (5) -- ViewRootImpl 的事件分发(Activity ViewGroup View )
Android Input (6) -- PhoneWindowManager中Power,BACK等按键处理流程
Android Input (8) -- ANR input event原理
Android事件传递整体流程简介
Android输入事件的源头是位于/dev/input/下的设备节点,而输入事件的终点是由WMS管理的某个窗口,最终由窗口中的View处理。最初的输入事件为内核生成的原始事件,
而最终交付给窗口的则是KeyEvent(键盘)或MotionEvent(鼠标和触摸屏)对象。输入事件由Native层进入到Java层的第一个函数是InputEventReceiver.dispatchInputEvent(),
这样我们的手指触摸事件(MotionEvent)就传递到Java层,到应用层的传递过程遵循如下顺序:Activity->Window->View;即View事件最先传递给Activity,
然后由Activity传递给Window,最后由Window传递给View;顶级View(DecorView)接收到事件后,就会按照事件分发机制去分发事件;事件到达Java层以后是谁将事件传递给Activity?
//事件传递整体流程:底层生成原始事件后,经过一列加工处理之后,将事件封装成MotionEvent、keyEvent,然后传递到Java层的InputEventReceiver.dispatchTouchEvent中,
事件到达Java层之后,如何一步步传递到Activity?以下调用堆栈可以看到事件如何用从InputEventReceive传递到Activity;事件传递到Activity之后,由Activity传递给Window(PhoneWindow),
最后由Window传递给顶级View;顶级View(DecorView)接收到事件后,就会按照事件分发机制去分发事件;本文主要是从Activity开始来分析事件分发机制;
目录
1.2 NativeInputEventReceiver ::consumeEvents
1.3 gInputEventReceiverClassInfo.dispatchInputEvent
2. ViewRootImpl对事件的派发(InputStage)
2.1 ViewRootImpl.java dispatchInputEvent/enqueueInputEvent
2.4 InputStage开始分发事件 dispatchTouchEvent
3. Activity ViewGroup View的事件分发 dispatchTouchEvent和 onTouchEvent
3.1 View ViewGroup DecorView 继承关系
3.2 DecorView dispatchTouchEvent
3.3 Activity dispatchTouchEvent
3.4 ViewGroup dispatchTouchEvent
Log Pattern1:
//事件详细信息,action表示事件类型,x,y表示事件发生的位置,deviceId是硬件设备的id值
EventTest: MainActivity dispatchTouchEvent: MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=408.94913, y[0]=416.38184, toolType[0]=TOOL_TYPE_MOUSE, buttonState=BUTTON_PRIMARY, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=498914, downTime=498914, deviceId=13, source=0x2002 }
System.err: java.lang.Exception: EventTest2
System.err: at .*********************.MainActivity.dispatchTouchEvent(MainActivity.java:68)
System.err: at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71)
System.err: at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:434)
System.err: at android.view.View.dispatchPointerEvent(View.java:12029)
System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4834)
//在onProcess方法中,进行事件类型的判断,然后根据不同的事件类型调用不同的处理方法
System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4644)
//在deliver中完成事件处理之后,调用finishInputEvent给输入系统一个反馈;
System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)
System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4322)
System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err: at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4379)
System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)
System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176) //1.5 InputStage.deliver()
System.err: at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6707)
System.err: at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6681)
System.err: at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6642) //1.4
System.err: at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6810) //调用到集成抽象类InputEventReceiver里面的WindowInputEventReceiver
//事件由native层正式进入到Java层
System.err: at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:187) //1.3 InputDiapatcher seedmsg后,fd触发handEvent调用到 dispatchInputEvent
System.err: at android.os.MessageQueue.nativePollOnce(Native Method) //1.1 handleEvent回调处理
System.err: at android.os.MessageQueue.next(MessageQueue.java:325)
System.err: at android.os.Looper.loop(Looper.java:142)
System.err: at android.app.ActivityThread.main(ActivityThread.java:6627)
System.err: at java.lang.reflect.Method.invoke(Native Method)
System.err: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
第3部分的流程图
第3部分的的Log pattern
写一个简单的例子,验证下。选择一个View,重写其onTouchEvent方法,然后通过dumpStack方法来打印出当前线程的调用栈信息。
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent, ev=" + event.getAction());
Thread.dumpStack();
return true;
}
06-22 13:25:21.368 7365 7365 D FrameLayoutEx: onTouchEvent, ev=0
06-22 13:25:21.368 7365 7365 W System.err: java.lang.Throwable: stack dump
06-22 13:25:21.368 7365 7365 W System.err: at java.lang.Thread.dumpStack(Thread.java:490)
06-22 13:25:21.368 7365 7365 W System.err: at com.ryg.reveallayout.ui.FrameLayoutEx.onTouchEvent(FrameLayoutEx.java:27)
06-22 13:25:21.368 7365 7365 W System.err: at android.view.View.dispatchTouchEvent(View.java:9294)
06-22 13:25:21.368 7365 7365 W System.err: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2547)
06-22 13:25:21.368 7365 7365 W System.err: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2240)
06-22 13:25:21.368 7365 7365 W System.err: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
06-22 13:25:21.369 7365 7365 W System.err: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
06-22 13:25:21.369 7365 7365 W System.err: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
06-22 13:25:21.369 7365 7365 W System.err: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
06-22 13:25:21.369 7365 7365 W System.err: at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
06-22 13:25:21.369 7365 7365 W System.err: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
06-22 13:25:21.369 7365 7365 W System.err: at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
06-22 13:25:21.369 7365 7365 W System.err: at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
06-22 13:25:21.369 7365 7365 W System.err: at android.app.Activity.dispatchTouchEvent(Activity.java:2765)
06-22 13:25:21.369 7365 7365 W System.err: at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
06-22 13:25:21.369 7365 7365 W System.err: at android.view.View.dispatchPointerEvent(View.java:9514)
06-22 13:25:21.369 7365 7365 W System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
06-22 13:25:21.370 7365 7365 W System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
06-22 13:25:21.371 7365 7365 W System.err: at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922)
06-22 13:25:21.371 7365 7365 W System.err: at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896)
06-22 13:25:21.371 7365 7365 W System.err: at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857)
06-22 13:25:21.371 7365 7365 W System.err: at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025)
06-22 13:25:21.371 7365 7365 W System.err: at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
06-22 13:25:21.371 7365 7365 W System.err: at android.os.MessageQueue.nativePollOnce(Native Method)
06-22 13:25:21.371 7365 7365 W System.err: at android.os.MessageQueue.next(MessageQueue.java:323)
06-22 13:25:21.371 7365 7365 W System.err: at android.os.Looper.loop(Looper.java:135)
06-22 13:25:21.371 7365 7365 W System.err: at android.app.ActivityThread.main(ActivityThread.java:5417)
06-22 13:25:21.371 7365 7365 W System.err: at java.lang.reflect.Method.invoke(Native Method)
06-22 13:25:21.371 7365 7365 W System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
06-22 13:25:21.371 7365 7365 W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit
onTouchEvent如下
09-05 09:28:07.840 7883 7883 W System.err: java.lang.Exception: Stack trace
09-05 09:28:07.840 7883 7883 W System.err: at java.lang.Thread.dumpStack(Thread.java:1348)
09-05 09:28:07.840 7883 7883 W System.err: at com.tsp.notification.MainActivity.onTouchEvent(MainActivity.java:86)
09-05 09:28:07.840 7883 7883 W System.err: at android.app.Activity.dispatchTouchEvent(Activity.java:3404)
09-05 09:28:07.840 7883 7883 W System.err: at com.tsp.notification.MainActivity.dispatchTouchEvent(MainActivity.java:81)
09-05 09:28:07.840 7883 7883 W System.err: at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
09-05 09:28:07.840 7883 7883 W System.err: at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:398)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.View.dispatchPointerEvent(View.java:12752)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5113)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4916)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4433)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4486)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4452)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4592)
09-05 09:28:07.840 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4460)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4649)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4433)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4486)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4452)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4460)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4433)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7099)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7068)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7029)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7202)
09-05 09:28:07.841 7883 7883 W System.err: at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:186)
09-05 09:28:07.841 7883 7883 W System.err: at android.os.MessageQueue.nativePollOnce(Native Method)
09-05 09:28:07.841 7883 7883 W System.err: at android.os.MessageQueue.next(MessageQueue.java:326)
09-05 09:28:07.841 7883 7883 W System.err: at android.os.Looper.loop(Looper.java:160)
1. 收到InputDispatcher事件的回调处理
第一部分内容可参考前面ViewRootImpl的input内容
1.1 handleEvent回调处理
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL); //consumeEvents 消耗事件
return status == OK || status == NO_MEMORY ? 1 : 0;
}
...
}
1.2 NativeInputEventReceiver ::consumeEvents
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
bool skipCallbacks = false;
for (;;) {
...
if (inputEventObj) {
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj, //gInputEventReceiverClassInfo.dispatchInputEvent
displayId);
...
}
}
}
1.3 gInputEventReceiverClassInfo.dispatchInputEvent
private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event, displayId);
}
2. ViewRootImpl对事件的派发(InputStage)
2.1 ViewRootImpl.java dispatchInputEvent/enqueueInputEvent
@frameworks/base/core/java/android/view/ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@Override
public void onInputEvent(InputEvent event, int displayId) {
enqueueInputEvent(event, this, 0, true);
}
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
QueuedInputEvent last = mPendingInputEventTail;
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
void doProcessInputEvents() {
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
q.mNext = null;
deliverInputEvent(q);
}
}
2.2 InputStage.deliver
//调用InputStage的各个方法deliver, 处理完事件后就会finishInputEvent来完成事件分发操作
private void deliverInputEvent(QueuedInputEvent q) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
}
InputStage stage;
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
2.3 各个InputStage
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,
构造了7个InputStage实现类,
- NativePreImeInputStage: 主要是为了将消息放到NativeActivity中去处理, NativeActivity和普通Acitivty的功能区别不大,只是很多代码都在native层去实现,这样执行效率更高,并且NativeActivity在游戏开发中很实用。
- ViewPreImeInputStage: 从名字中就可得知,最后会调用Acitivity的所有view的onkeyPreIme方法,这样就给View在输入法处理key事件之前先得到消息并处理的机会。
- ImeInputStage: ImeInputStage的onProcess方法会调用InputMethodManager的dispatchInputEvent方法处理消息。
- EarlyPostImeInputStage: 屏幕上有焦点的View会高亮显示,用来提示用户焦点所在。
- NativePostImeInputStage: 为了让IME处理完消息后能先于普通的Activity处理消息。
- ViewPostImeInputStage: Acitivity和view处理各种消息。
- SyntheticInputStage: 流水线的最后一级,经过层层过滤之后,到达这里的消息已经不多了,例如手机上的虚拟按键消息。
那么Activity和View的事件处理主要对应的InputStage是ViewPostImeInputStage。
//InputStage.deliver完之后,就会next到其他inputStage处理,这里到View的ViewPostImeInputStage来处理
System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4644)
System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)
System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4322)
System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err: at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4379)
System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)
System.err: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4229)
System.err: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4195)
System.err: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4203)
System.err: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4176)
2.4 InputStage开始分发事件 dispatchTouchEvent
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 {
apply(q, onProcess(q));
}
}
protected void onDeliverToNext(QueuedInputEvent q) {
if (DEBUG_INPUT_STAGES) {
Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
}
if (mNext != null) {
mNext.deliver(q); //next deliver()
} else {
finishInputEvent(q);
}
}
final class ViewPostImeInputStage extends InputStage {
public ViewPostImeInputStage(InputStage next) {
super(next);
}
@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); //processPointerEvent
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
return processTrackballEvent(q);
} else {
return processGenericMotionEvent(q);
}
}
}
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
mAttachInfo.mUnbufferedDispatchRequested = false;
mAttachInfo.mHandlingPointerEvent = true;
boolean handled = mView.dispatchPointerEvent(event); //mView继承关系调用
int action = event.getActionMasked();
...
return handled ? FINISH_HANDLED : FORWARD;
}
//会调用到DecorView dispatchTouchEvent
System.err: at .*********************.MainActivity.dispatchTouchEvent(MainActivity.java:68)
System.err: at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71)
System.err: at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:434)
System.err: at android.view.View.dispatchPointerEvent(View.java:12029)
System.err: at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4834)
3. Activity ViewGroup View的事件分发 dispatchTouchEvent和 onTouchEvent
InputEvent有2个子类:KeyEvent和MotionEvent,其中KeyEvent表示键盘事件,而MotionEvent表示点击事件。
3.1 View ViewGroup DecorView 继承关系
//View继承关系如下
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker{...}
public class FrameLayout extends ViewGroup {...}
public abstract class ViewGroup extends View implements ViewParent, ViewManager{..}
接着上面mView.dispatchPointerEvent(event)分析
@frameworks/base/core/java/android/view/View.java
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}
3.2 DecorView dispatchTouchEvent
根据mView继承调用
//先是子类 DecorView
@frameworks/base/core/java/com/android/internal/policy/DecorView.java
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
3.3 Activity dispatchTouchEvent
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback, //继承 Window.Callback
{
//调用Activity dispatchTouchEvent,可见先调用各个DispatchTouchEvent,最后才调用onTouchEvent,因此最早 dispatchTouchEvent,应用最晚 onTouchEvent
@Activity.java
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
3.4 ViewGroup dispatchTouchEvent
//会调用到
@frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
@frameworks/base/core/java/com/android/internal/policy/DecorView.java
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker{...}
public class FrameLayout extends ViewGroup {...}
public abstract class ViewGroup extends View implements ViewParent, ViewManager{..}
//进入ViewGroup
@frameworks/base/core/java/android/view/ViewGroup.java
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
...
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
}
...
if (mFirstTouchTarget == null) {
// No touch targets so treat this as an ordinary view.
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
}
return handled;
}
//调用View dispatchTouchEvent
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
final boolean handled;
...
// Perform any necessary transformations and dispatch.
if (child == null) {
handled = super.dispatchTouchEvent(transformedEvent);
} else {
final float offsetX = mScrollX - child.mLeft;
final float offsetY = mScrollY - child.mTop;
transformedEvent.offsetLocation(offsetX, offsetY);
if (! child.hasIdentityMatrix()) {
transformedEvent.transform(child.getInverseMatrix());
}
handled = child.dispatchTouchEvent(transformedEvent);
}
}
3.5 View dispatchTouchEvent
@View.java
public boolean dispatchTouchEvent(MotionEvent event) {
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) { //mOnTouchListener存在就会返回并且拦截事件,就不会走下面的 onTouchEvent,这样应用就可以处理
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
return result;
}