18、ViewRootImpl事件接收:setView()中建立InputChannel,WindowInputEventReceiver的创建
setView()中的InputChannel接收逻辑我们先找到ViewRootImpl.setView()这个方法。它是在ActivityThread.handleResumeActivity()里被调用的传入了宿主View和对应的WindowManager.LayoutParams。关键代码在这里public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { if (mView null) { mView view; ... // 1. 创建InputChannel InputChannel inputChannel null; if ((mWindowAttributes.inputFeatures WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) 0) { inputChannel new InputChannel(); } ... // 2. 通过Binder调用WMS添加窗口 res mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel, mTempInsets, mTempControls); ... // 3. 创建WindowInputEventReceiver if (mInputChannel ! null) { if (mInputQueueCallback ! null) { mInputQueue new InputQueue(); mInputQueueCallback.onInputQueueCreated(mInputQueue); } mInputEventReceiver new WindowInputEventReceiver(mInputChannel, Looper.myLooper()); } ... } } }嗯这里有三步我一个个拆开讲。第一步创建InputChannel对象注意看这里new出来的InputChannel只是一个空壳。它还没有和任何底层的文件描述符绑定。真正的通道建立是在WMS那边完成的。核心要点应用端new InputChannel()只是分配了一个Java对象真正的SocketPair创建在WMS的addWindow()中。WMS会把服务端通道填进这个对象然后通过Binder传回来。我个人习惯在分析这类代码时先搞清楚「谁创建、谁填充、谁使用」。这里就是应用端创建空InputChannel对象WMS端创建SocketPair填充服务端和客户端通道应用端接收填充好的InputChannel开始监听第二步mWindowSession.addToDisplay()这个Binder调用我上一章详细讲过。它会走到WMS的addWindow()方法里完成InputChannel的创建和填充。调用完成后mInputChannel这个成员变量就不再是空的了。它里面包含了客户端端的文件描述符。你可以通过mInputChannel.getFd()拿到它——不过说实话我们一般不会直接操作fd而是通过InputEventReceiver来封装。小提示我在项目中遇到过一个问题——某些定制ROM在addToDisplay返回后mInputChannel仍然是空的。后来发现是WMS的InputChannel创建逻辑被改了。排查时可以用adb shell dumpsys input查看窗口的InputChannel状态确认是否注册成功。第三步创建WindowInputEventReceiver这一步是关键中的关键。我们来看WindowInputEventReceiver的构造final class WindowInputEventReceiver extends InputEventReceiver { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); } ... }它继承自InputEventReceiver。而InputEventReceiver的构造方法会调用native层public InputEventReceiver(InputChannel inputChannel, Looper looper) { ... mReceiverPtr nativeInit(new WeakReferenceInputEventReceiver(this), inputChannel, looper.getQueue()); }这个nativeInit()方法在C层做了三件重要的事创建一个NativeInputEventReceiver对象把这个对象和InputChannel的fd绑定把fd注册到Looper的epoll中开始监听可读事件说白了就是把InputChannel的fd挂到了主线程的Looper上。一旦有触摸事件从WMS发过来fd就会变成可读状态Looper就会回调NativeInputEventReceiver的handleEvent()方法。注意WindowInputEventReceiver是在主线程创建的所以它使用的是主线程的Looper。这意味着所有输入事件的分发都是在主线程上执行的。如果你在主线程做耗时操作触摸事件就会卡住——嗯这就是为什么「应用无响应」时屏幕点不动的原因之一。InputChannel的传递链路总结为了让你看得更清楚我画了个简化的流程表步骤所在位置做了什么1ViewRootImpl.setView()new InputChannel() 创建空对象2WMS.addWindow()创建SocketPair填充InputChannel3ViewRootImpl.setView()接收填充后的InputChannel4new WindowInputEventReceiver()创建接收器注册到Looper5NativeInputEventReceiver监听fd事件到来时回调我曾经踩过的坑讲到这里我想分享一个真实案例。曾经我优化一个视频播放器的触摸响应延迟。发现从手指触屏到MotionEvent到达View总是多出2-3ms的延迟。排查了很久最后发现是WindowInputEventReceiver的创建时机问题。原来在那个项目中有人在Activity.onCreate()里手动调了setContentView()之后又异步做了一些初始化操作。这导致ViewRootImpl.setView()被延迟执行了。而InputChannel的建立和Receiver的注册都卡在了setView()里。解决方案很简单确保setContentView()之后尽快让ViewRootImpl完成setView()。说白了就是不要在onCreate()里做太多耗时操作尤其是那些在setContentView()之后才执行的任务。小结这一章我们重点看了ViewRootImpl.setView()中InputChannel的建立和WindowInputEventReceiver的创建。记住三个关键点InputChannel是WMS创建的应用端只是接收WindowInputEventReceiver把fd挂到主线程Looper上所有触摸事件的分发都在主线程执行

相关新闻

eFuse与MCU协同:嵌入式系统智能电源保护设计

eFuse与MCU协同:嵌入式系统智能电源保护设计

1. 传统保险丝在嵌入式系统里的三个硬伤,以及eFuse带来的解法1.1 传统保险丝和自恢复保险丝的局限在24V供电的嵌入式设备上,我见过太多次保险丝被顺手焊上,然后整个团队围在通电瞬间查冒烟点的场景。保险丝确实能在过流时断开,但断…

2026/10/8 6:40:36 阅读更多 →
AI工程师的动态认知操作系统:构建个人日报系统

AI工程师的动态认知操作系统:构建个人日报系统

1. 这份“AI 日报”不是新闻简报,而是一份动态认知操作系统你点开这个标题,第一反应可能是:又一份AI行业快讯?刷两眼就划走?我试过——去年整整三个月,每天早上花七分钟扫一遍各种“AI Daily”“AI Pulse”…

2026/10/8 6:40:35 阅读更多 →
AI Agent 不仅仅是调 API:拆解七要素与工程落地全指南

AI Agent 不仅仅是调 API:拆解七要素与工程落地全指南

1. Agent 到底是什么:先搞清楚七要素干 Agent 工程这两年,我最大的感受是:大家一上来就聊 LangGraph、AutoGen、多智能体协作,结果连最基本的 Agent 定义都是模糊的。其实剥掉所有框架和概念外衣,一个能被工程化落地的…

2026/10/8 6:40:35 阅读更多 →

最新新闻

从画风管到批量出图,IDC国产CAD双料第一的实力够硬吗

从画风管到批量出图,IDC国产CAD双料第一的实力够硬吗

做暖通设计的人都清楚,日常工作远不止"画几根风管"那么轻松。一个稍大的公建项目,光是和建筑、结构、给排水、电气几个专业来回提资、对图,就足够让人疲于奔命;到了出图阶段,几十张图纸要逐张设置参数、反复…

2026/10/8 7:04:50 阅读更多 →
付款条款怎么谈:4种常见模式与各自的坑

付款条款怎么谈:4种常见模式与各自的坑

做采购的、做销售的朋友,最容易在付款条款上扯皮。因为付款条款牵涉的是真金白银的现金流,双方的利益天然对立。下面把常见的4种模式摆出来,说说各自的风险点在哪。模式一:先款后货 对方先付钱,再发货或者提供服务。 对…

2026/10/8 7:04:50 阅读更多 →
Gondolin快照教程:micro-VM磁盘检查点如何生成与快速恢复

Gondolin快照教程:micro-VM磁盘检查点如何生成与快速恢复

Gondolin快照教程:micro-VM磁盘检查点如何生成与快速恢复 【免费下载链接】gondolin Experimental Linux microvm setup with a TypeScript Control Plane as Agent Sandbox 项目地址: https://gitcode.com/gh_mirrors/go/gondolin Gondolin 是一款在本地运行…

2026/10/8 7:04:50 阅读更多 →
Superpowers开发工具链:Claude Code+Cursor+Antigravity协同架构解析

Superpowers开发工具链:Claude Code+Cursor+Antigravity协同架构解析

1. 项目概述:Superpowers 不是超能力,而是开发者效率革命的代号“Superpowers”这个词最近在开发者圈子里炸开了锅——它既不是漫威电影里的变种人设定,也不是什么玄学概念,而是一套正在快速落地、真实改变日常编码节奏的智能开发…

2026/10/8 7:04:50 阅读更多 →
Spring AI、LangChain4j、AgentScope、Embabel 四大 AI 框架深度对比与代码实战

Spring AI、LangChain4j、AgentScope、Embabel 四大 AI 框架深度对比与代码实战

1. 引言 2024 年以来,大模型应用的开发范式从「手工拼接 Prompt」快速演进为「框架驱动的工程化开发」。对于后端工程师,尤其是 Java 技术栈团队,选择一款合适的 AI 框架决定了项目初期的开发效率、中期的可维护性以及后期的扩展能力。 市面上…

2026/10/8 7:04:50 阅读更多 →
SSM校园图书角管理系统:借阅状态机与并发控制实战

SSM校园图书角管理系统:借阅状态机与并发控制实战

简介:这份资源是面向计算机相关专业学生与Java初学者的大学生校园图书角管理系统完整项目源码,采用Java语言、SSM框架、JSP技术与MySQL数据库,基于B/S架构开发,可作为毕业设计、课程设计或SSM框架练手参考。系统功能覆盖系统主页、…

2026/10/8 7:03:49 阅读更多 →

日新闻

抖音用户主页视频数据爬虫详解:点赞、收藏、分享字段抓取与 TaoToken 统一 Key 配置

抖音用户主页视频数据爬虫详解:点赞、收藏、分享字段抓取与 TaoToken 统一 Key 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:00:03 阅读更多 →
AI 编程 Trae 国内版与国际版一篇讲透:TaoToken 统一 Key 接入实测

AI 编程 Trae 国内版与国际版一篇讲透:TaoToken 统一 Key 接入实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:00:06 阅读更多 →
Claude Desktop 配置第三方推理接口教程:用 TaoToken 统一 Key 打通 API 调用

Claude Desktop 配置第三方推理接口教程:用 TaoToken 统一 Key 打通 API 调用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:00:07 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:13 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 14:34:12 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 11:43:46 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →