写点什么

Android 知识笔记:记录 2 个 “容易误解 (1),【干货】

用户头像
Android架构
关注
发布于: 刚刚

2、Input 系统—InputReader 线程:loop 起来让 EventHub 调用 getEvent()不断的从/dev/input/文件夹下读取输入事件。然后转换成 EventEntry 事件加入到 InputDispatcher 的 mInboundQueue。


3、Input 系统—InputDispatcher 线程:从 mInboundQueue 队列取出事件,转换成 DispatchEntry 事件加入到 connection 的 outboundQueue 队列。再然后开始处理分发事件 (比如分发到 ViewRootImpl 的 WindowInputEventReceiver 中),取出 outbound 队列,放入 waitQueue.


4、Input 系统—UI 线程:创建 socket pair,分别位于”InputDispatcher”线程和 focused 窗口所在进程的 UI 主线程,可相互通信。


这里只说大概,详情请看 gityuan 的这篇文章 Input 系统—事件处理全过程,文章 3.3.3 小节讲的是 input 系统事件从 Native 层分发 Framework 层的 InputEventReceiver.dispachInputEvent()。


http://gityuan.com/2016/12/31/input-ipc/


Framework 层


//InputEventReceiver.dispachInputEvent()


private void dispatchInputEvent(int seq, InputEvent event) {


mSeqMap.put(event.getSequenceNumber(), seq);


onInputEvent(event);


}


ViewRootImpl.WindowInputEventReceiver


Native 层通过 JNI 执行 Framework 层的 InputEventReceiver.dispachInputEvent(),而真正调用的是继承了 InputEventReceiver 的 ViewRootImpl.WindowInputEventReceiver。


所以这里执行的 WindowInputEventReceiver 的 dispachInputEvent():


final class WindowInputEventReceiver extends InputEventReceiver {


public void onInputEvent(InputEvent event) {


enqueueInputEvent(event, this, 0, true);


}


...


}


ViewRootImpl


void enqueueInputEvent(InputEvent event,


InputEventReceiver receiver, int flags, boolean processImmediately) {


...


if (processImmediately) {


//关键点:执行 Input 事件


doProcessInputEvents();


} else {


//走一遍 Handler 延迟处理事件


scheduleProcessInputEvents();


}


}


void doProcessInputEvents() {


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);


long eventTime = q.mEvent.getEventTimeNano();


long oldestEventTime = eventTime;


if (q.mEvent instanceof MotionEvent) {


MotionEvent me = (MotionEvent)q.mEvent;


if (me.getHistorySize() > 0) {


oldestEventTime = me.getHistoricalEventTimeNano(0);


}


}


mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);


//关键点:进一步派发事件处理


deliverInputEvent(q);


}


...


}


private void deliverInputEvent(QueuedInputEvent q) {


Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",


q.mEvent.getSequenceNumber());


if (mInputEventConsistencyVerifier != null) {


mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);


}


InputStage stage;


if (q.shouldSendToSynthesizer()) {


stage = mSyntheticInputStage;


} else {


stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;


}


if (stage != null) {


//关键点:上面决定将事件派发到那个 InputStage 中处理


stage.deliver(q);


} else {


finishInputEvent(q);


}


}


ViewRootImpl.ViewPostImeInputStage


前面事件会派发到 ViewRootImpl.ViewPostImeInputStage 中处理,它的父类 InputStage.deliver()方法会调用 apply()来处理 Touch 事件:


@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) {


//关键点:执行分发 touch 事件


return processPointerEvent(q);


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


...


//关键点:mView 分发 Touch 事件,mView 就是 DecorView


boolean handled = mView.dispatchPointerEvent(event);


maybeUpdatePointerIcon(event);


maybeUpdateTooltip(event);


...


}


DecorView


如果你熟悉安卓的 Window,Activity 和 Dialog 对应的 ViewRootImpl 成员 mView 就是 DecorView,View 的 dispatchPointerEvent()代码如下:


//View.java


public final boolean dispatchPointerEvent(MotionEvent event) {


if (event.isTouchEvent()) {


//分发 Touch 事件


return dispatchTouchEvent(event);


} else {


return dispatchGenericMotionEvent(event);


}


}


因为 DecorView 继承 FrameLayout,上面所以会调用 DecorView 的 dispatchTouchEvent():


@Override


public boolean dispatchTouchEvent(MotionEvent ev) {


final Window.Callback cb = mWindow.getCallback();


return cb != null && !mWindow.isDestroyed(


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


) && mFeatureId < 0


? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);


}


上面 Window.Callback 都被 Activity 和 Dialog 实现,所以变量 cb 可能就是 Activity 和 Dialog。


Activity


当上面 cb 是 Activity 时,执行 Activity 的 dispatchTouchEvent():


public boolean dispatchTouchEvent(MotionEvent ev) {


if (ev.getAction() == MotionEvent.ACTION_DOWN) {


onUserInteraction();


}


if (getWindow().superDispatchTouchEvent(ev)) {//关键点:getWindow().superDispatchTouchEvent(ev)


return true;


}


return onTouchEvent(ev);


}


如果你熟悉安卓的 Window,Activity 的 getWindow()拿到的就是 PhoneWindow,下面是 PhoneWindow 的代码:


//PhoneWindow.java


@Override


public boolean superDispatchTouchEvent(MotionEvent event) {


//调用 DecorView 的 superDispatchTouchEvent

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android知识笔记:记录 2 个 “容易误解(1),【干货】