记录日期:2026-08-26
项目仓库:/Users/liang/AndroidStudioProjects/CusumptionMachine
实施分支:simplify_menu_pay
菜单消费账单核对弹框关闭后再次打开,扫码器可能连续响多次,但前几次没有发起支付。现场日志确认三次扫码分别由三个不同线程读取,前两个线程属于已经关闭业务回调、但仍阻塞在串口 read() 的旧实例;数据被旧线程消费后直接丢弃,第三次才由当前账单会话处理。
优卡特扫码器原实现中,每个页面或弹框都会重新打开 /dev/ttyS3 并创建读取线程。关闭时虽然调用了 interrupt() 和串口关闭,但设备驱动无法保证立即唤醒阻塞中的 InputStream.read()。旧线程可能继续等待并与新线程竞争后续扫码数据。
YoukateQrcodePortManager,作为 /dev/ttyS3 的唯一物理串口所有者,进程内只创建一个读取线程。YoukateQrcodeSerialPortScanner 改为轻量业务会话,不再直接打开或关闭物理串口;支持 resume()、pause() 和永久 close()。LatestSessionDispatcher,最后注册的页面获得当前会话所有权;旧会话关闭不会清除新会话。onStart()/onStop()。onStop() 兜底释放会话和停止倒计时。app/src/main/java/com/cpt/cusumption/devices/serial/LatestSessionDispatcher.javaapp/src/main/java/com/cpt/cusumption/devices/youkate/YoukateQrcodePortManager.javaapp/src/main/java/com/cpt/cusumption/devices/youkate/YoukateQrcodeSerialPortScanner.javaapp/src/main/java/com/cpt/cusumption/activity/FreeActivity.javaapp/src/main/java/com/cpt/cusumption/activity/FreeNoKeyboardActivity.javaapp/src/main/java/com/cpt/cusumption/activity/QuotaActivity.javaapp/src/main/java/com/cpt/cusumption/activity/QuotaNoKeyboardActivity.javaapp/src/main/java/com/cpt/cusumption/activity/OrderVerifyActivity.javaapp/src/main/java/com/cpt/cusumption/activity/MealServedActivity.javaapp/src/main/java/com/cpt/cusumption/view/YoukateQrcodeScanPop.javaapp/src/main/java/com/cpt/cusumption/view/MenuBillCheckPop.javaapp/src/test/java/com/cpt/cusumption/devices/serial/LatestSessionDispatcherTest.javaLatestSessionDispatcherTest,确认生产类缺失时测试编译失败。LatestSessionDispatcherTest 共 4 个测试全部通过,覆盖最后会话独占、旧会话关闭不影响新会话、会话替换后丢弃排队结果、当前会话关闭后拒绝迟到结果。JAVA_HOME=/Users/liang/Library/Java/JavaVirtualMachines/corretto-1.8.0_482/Contents/Home bash gradlew :app:testDebugUnitTest :app:assembleDebug:通过,BUILD SUCCESSFUL。app/build/outputs/apk/debug/app-debug.apk。/dev/ttyS3;伟邦、米果扫码和优卡特刷卡串口未改变。