Android Input (5) -- ViewRootImpl 的事件分发(Activity ViewGroup View )

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 (7) -- 模块的锁检测

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开始来分析事件分发机制;

 

目录

Log Pattern1:

第3部分的流程图

第3部分的的Log pattern

1. 收到InputDispatcher事件的回调处理

1.1 handleEvent回调处理

1.2 NativeInputEventReceiver ::consumeEvents

1.3 gInputEventReceiverClassInfo.dispatchInputEvent

2. ViewRootImpl对事件的派发(InputStage)

2.1 ViewRootImpl.java dispatchInputEvent/enqueueInputEvent

2.2 InputStage.deliver

2.3 各个InputStage

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

3.5 View 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;
}

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值