日期:2026-07-31
已完成应用侧修复:语音加载、加载完成后的播放以及页面生命周期释放现在通过同一资源门禁串行协调。页面先释放 SoundPool 后,晚到的异步加载回调会被忽略,不再访问已经置空或释放的 SoundPool。
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.media.SoundPool.play(...)' on a null object reference at com.cpt.zhct.weighting.utils.SoundPoolPlayer.play(SoundPoolPlayer.java:82) at com.cpt.zhct.weighting.utils.SoundPoolPlayer$1.onLoadComplete(SoundPoolPlayer.java:66)
根因是 SoundPool.load() 异步执行。语音尚未加载完成时,Activity 或 Fragment 的 onStop() 可能先调用 release(),随后加载完成回调仍调用 play(),形成释放后访问竞态。
SoundPoolPlayer.java:监听一次性注册;使用回调 sampleId;加载失败不播放;加载、播放和释放经过同一资源门禁;释放前移除监听。SoundPoolPlaybackGate.java:协调活动资源操作与释放,拒绝释放后的晚到回调。SoundPoolPlaybackGateTest.java:覆盖释放后忽略播放和释放等待正在执行播放两种场景。回归测试先在资源门禁尚未实现时按预期编译失败;完成最小实现后,定向测试返回 BUILD SUCCESSFUL in 6s。
./gradlew testDebugUnitTest assembleDebug --console=plain
使用 JDK 8 执行,结果为 BUILD SUCCESSFUL in 34s。
app/build/outputs/apk/debug/app-debug.apk。当前分支为 fun_tray_recognition_control。本次未执行暂存、提交、推送或分支切换;工作区原有硬件管理、红外弹框布局、相关测试和 output/ 内容未纳入本次改动。