1. 问题现象与背景分析
在移动端混合开发场景中,我们经常会遇到物理键盘与软键盘切换的场景。最近在维护一个基于C++跨平台框架开发的金融交易APP时,发现了一个棘手的UI线程死锁问题:当用户在交易页面从物理键盘切换到软键盘输入后,快速跳转到其他页面时,偶现整个UI线程卡死,导致应用无响应。
通过日志分析发现,问题出现在keyboardClosed事件的延迟广播上——当软键盘关闭事件被延迟触发时,回调函数尝试操作一个已经被销毁的页面控件,而该控件的销毁过程又需要等待UI线程释放锁,从而形成了典型的循环等待死锁。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈与运行环境分析
2.1 框架特性
项目使用的跨平台框架具有以下关键特性:
- 采用C++14标准编写核心逻辑
- 使用平台原生控件实现UI渲染
- 事件系统采用订阅-发布模式
- 页面生命周期管理基于引用计数
2.2 键盘处理机制
框架对键盘事件的处理流程如下:
- 物理键盘事件直接通过系统API传递
- 软键盘状态变化通过以下路径通知:
- Android: 监听View的onSizeChanged
- iOS: 监听UIKeyboardWillShowNotification
- 键盘关闭事件统一封装为keyboardClosed信号
3. 问题根因深度剖析
3.1 事件时序分析
通过埋点日志还原问题发生时的关键时序:
text复制[时间戳] 用户点击输入框 -> 软键盘弹出
[时间戳] 用户点击"跳转"按钮 -> 开始页面切换
[时间戳] 旧页面开始销毁流程
[时间戳] 系统触发软键盘关闭动画
[时间戳] 旧页面控件销毁完成
[时间戳+300ms] keyboardClosed事件到达消息队列
[时间戳+300ms] 事件回调尝试访问已销毁控件
3.2 死锁形成条件
死锁产生的四个必要条件在本案例中全部满足:
- 互斥条件:UI线程锁被页面销毁流程持有
- 请求与保持:事件回调等待锁释放
- 不剥夺条件:系统无法强制回收资源
- 循环等待:销毁流程等待事件处理完成
4. 解决方案设计与实现
4.1 方案选型对比
| 方案 | 实现复杂度 | 性能影响 | 兼容性 | 维护成本 |
|------|------
