react-native-sound首次播放无声音及多次播放缺失问题求助
问题排查与修复方案
核心问题分析
- 音频初始化时机错误:把
new Sound()放在组件顶层,每次组件渲染都会重新创建实例,且未等待加载完成就调用play,这是首次无声音的主要原因。 - 递归中的音频停止逻辑错误:在递归调用
movePawnByStep后立即调用stop,会中断当前正在播放的音频,导致部分播放缺失。 - 未重置音频播放位置:重复播放时没有将音频重置到开头,可能导致音频处于结束状态无法再次播放。
- 播放回调处理不当:回调中直接再次调用
play,未判断音频当前状态,容易引发播放冲突。
修复后的代码
import Sound from 'react-native-sound'; import { useEffect, useRef } from 'react'; // 假设FINISHED和setTestState是已定义的变量/函数 const FINISHED = 'finished'; export default function App(){ const stepAudio = useRef(null); const isAudioLoaded = useRef(false); // 仅初始化一次音频 useEffect(() => { stepAudio.current = new Sound('step.mp3', Sound.MAIN_BUNDLE, (error) => { if (error) { console.log('Error Step Audio', error); return; } // 标记音频加载完成 isAudioLoaded.current = true; // 设置单次播放,完成后自动重置位置 stepAudio.current.setNumberOfLoops(0); }); // 组件卸载时释放音频资源 return () => { if (stepAudio.current) { stepAudio.current.release(); } }; }, []); async function playStepAudio() { if (!isAudioLoaded.current || !stepAudio.current) return; // 重置音频到起始位置,确保每次播放从头开始 stepAudio.current.setCurrentTime(0); return new Promise((resolve) => { stepAudio.current.play((success) => { if (!success) { console.log('Audio playback failed'); } resolve(success); }); }); } async function movePawnByStep(prevPosition, newPostion, piece, areaIndicator, finished = null) { // 等待音频播放完成后再执行后续逻辑 await playStepAudio(); piece.position = areaIndicator + ++prevPosition; piece.updateTime = Date.now(); if (prevPosition < newPostion) { setTimeout(() => { movePawnByStep(prevPosition, newPostion, piece, areaIndicator, finished); setTestState(prev => !prev); }, 100); } else { if (finished !== null) { piece.position = FINISHED; piece.updateTime = Date.now(); } setTestState(prev => !prev); } } }
关键改动说明
- 用useEffect初始化音频:确保音频只被创建一次,等待加载完成后才允许播放,彻底解决首次调用时音频未就绪的问题。
- 新增playStepAudio工具函数:统一处理音频重置和播放逻辑,返回Promise让播放流程可控,每次播放前强制重置到起始位置。
- 移除错误的stop调用:递归过程中不需要手动终止音频,让音频自然播放完成;若需控制播放时长,可在play回调中处理。
- 组件卸载时释放资源:避免内存泄漏,符合react-native-sound的最佳实践。
- 简化递归逻辑:去掉setTimeout中不必要的await和clearTimeout,避免异步嵌套导致的音频冲突。
额外注意事项
- 确认
step.mp3文件路径正确,放在对应平台的资源目录(iOS的Resources或Android的raw目录)。 - 若需要音频与移动动画严格同步,可调整setTimeout延迟时间,或改用
requestAnimationFrame替代。 - 测试时检查设备静音状态及react-native-sound的权限配置(如Android的音频权限)。
内容的提问来源于stack exchange,提问作者Gursahb Webcyst
相关产品推荐
相关产品推荐

