点击事件是如何传递给Activity的

事件从Window传递给Activity,在windowgloble的addview方法中会创建InputChannel、InputQueue和WindowInputEventReceiver来接受点击事件的消息。

ViewRootImpl中有个方法

 private void scheduleProcessInputEvents() {
        if (!mProcessInputEventsScheduled) {
            mProcessInputEventsScheduled = true;
            Message msg = mHandler.obtainMessage(MSG_PROCESS_INPUT_EVENTS);
            msg.setAsynchronous(true);
            mHandler.sendMessage(msg);
        }
    }

我们看是如何被处理的

 case MSG_PROCESS_INPUT_EVENTS:
                mProcessInputEventsScheduled = false;
                doProcessInputEvents();
                break;

会调用doProcessInputEvents方法

 void doProcessInputEvents() {
        // Deliver all pending input events in the queue.
        while (mPendingInputEventHead != null) {
            QueuedInputEvent q = mPendingInputEventHead;
            mPendingInputEventHead = q.mNext;
            if (mPendingInputEventHead == null) {
                mPendingInputEventTail = null;
            }
            q.mNext = null;

            mPendingInputEventCount -= 1;
            Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                    mPendingInputEventCount);

            deliverInputEvent(q);
        }
private void deliverInputEvent(QueuedInputEvent q) {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
        try {
            if (mInputEventConsistencyVerifier != null) {
                mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
            }

            InputStage stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
            if (stage != null) {
                stage.deliver(q);
            } else {
                finishInputEvent(q);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }

在ViewRootImpl中,有一系列类似于InputStage(输入事件舞台)的概念,每种InputStage可以处理一定的事件类型,比如AsyncInputStage、ViewPreImeInputStage、ViewPostImeInputStage等。当一个InputEvent到来时,ViewRootImpl会寻找合适它的InputStage来处理。对于点击事件来说,ViewPostImeInputStage可以处理它,ViewPostImeInputStage中,有一个processPointerEvent方法,如下,它会调用mView的dispatchPointerEvent方法,注意,这里的mView其实就是DecorView。

 private int processPointerEvent(QueuedInputEvent q) {
            final MotionEvent event = (MotionEvent)q.mEvent;

            // Translate the pointer event for compatibility, if needed.
            if (mTranslator != null) {
                mTranslator.translateEventInScreenToAppWindow(event);
            }

            // Enter touch mode on down or scroll.
            final int action = event.getAction();
            if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
                ensureTouchMode(true);
            }

            // Offset the scroll position.
            if (mCurScrollY != 0) {
                event.offsetLocation(0, mCurScrollY);
            }

            // Remember the touch position for possible drag-initiation.
            if (event.isTouchEvent()) {
                mLastTouchPoint.x = event.getRawX();
                mLastTouchPoint.y = event.getRawY();
            }
            return FORWARD;
        }

我们看View中的dispatchPointerEvent,因为DecorView继承自View

  public final boolean dispatchPointerEvent(MotionEvent event) {
        if (event.isTouchEvent()) {
            return dispatchTouchEvent(event);
        } else {
            return dispatchGenericMotionEvent(event);
        }
    }

然后调用了DecorView的dispatchTouchEvent

  @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            final Callback cb = getCallback();
            return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)
                    : super.dispatchTouchEvent(ev);
        }

这里的cb就是Activity对象。

你可能感兴趣的:(点击事件是如何传递给Activity的)