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

来源:互联网 发布:网络教学的优缺点英语 编辑:程序博客网 时间:2024/05/16 08:20

事件从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对象。

0 0
原创粉丝点击