React Native中使用expo-av播放服务器音频报错求助
解决expo-av播放音频时"Cannot complete operation because sound is not loaded"错误
错误原因
初始渲染时audioStatus为false,触发useEffect执行else分支,尝试对未加载的Sound实例调用stopAsync()和unloadAsync()——这两个方法要求Sound必须处于已加载状态,因此抛出错误。
解决方案
- 初始化
sound状态为null,避免提前创建未加载的无效Sound实例 - 根据播放状态动态创建/销毁Sound实例,添加清理函数防止内存泄漏
- 操作Sound实例前先判断其是否存在,避免对未初始化实例执行方法
修复后的完整代码
import React, { useState, useEffect } from 'react'; import { Button } from 'react-native'; import { Audio } from 'expo-av'; export default function App() { const [isPlaying, setIsPlaying] = useState(false); const [sound, setSound] = useState(null); useEffect(() => { const handleAudio = async () => { if (isPlaying) { // 创建新实例并加载音频 const newSound = new Audio.Sound(); try { await newSound.loadAsync('https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3'); await newSound.playAsync(); setSound(newSound); } catch (e) { console.error('播放失败:', e); setIsPlaying(false); } } else { // 仅当实例存在时执行停止/卸载 if (sound) { try { await sound.stopAsync(); await sound.unloadAsync(); } catch (e) { console.error('停止失败:', e); } finally { setSound(null); } } } }; handleAudio(); // 组件卸载时自动清理资源 return () => { sound?.unloadAsync(); }; }, [isPlaying, sound]); return ( <Button color={isPlaying ? 'red' : 'green'} title={isPlaying ? '暂停' : '播放'} onPress={() => setIsPlaying(!isPlaying)} /> ); }
关键优化点
- 初始状态优化:
sound初始为null,避免创建未加载的无效实例 - 条件校验:执行停止操作前先检查
sound是否存在,跳过无效操作 - 清理机制:组件卸载时自动卸载Sound实例,防止内存泄漏
- 状态同步:加载成功后再将实例存入状态,确保后续操作的有效性
- 错误处理增强:加载/播放失败时重置播放状态,避免UI与实际音频状态不一致
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

