Expo中Android模拟器出现Player is accessed on wrong thread错误求助
Expo Audio 线程错误与卸载失败问题修复
错误情况
- 应用重载时触发线程错误:
Player is accessed on the wrong thread.
Current thread: 'mqt_native_modules'
Expected thread: 'main'
- 卸载声音时日志报错:
LOG Sound loaded successfully
ERROR Error unloading sound: [Error: Player does not exist.]
测试代码
import { Audio } from 'expo-av'; useEffect(() => { const sound = new Audio.Sound(); const loadAndPlaySound = async () => { try { await sound.loadAsync(require('../../sounds/app_notification.mp3')); await sound.playAsync(); console.log('Sound played successfully'); } catch (error) { console.error('Error loading or playing sound:', error); } }; loadAndPlaySound(); return () => { const unloadSound = async () => { try { await sound.unloadAsync(); console.log('Sound unloaded successfully'); } catch (error) { console.error('Error unloading sound:', error); } }; unloadSound(); }; }, []);
修复方案
核心问题
- 卸载操作在非主线程执行,触发ExoPlayer的线程检查错误;
- 组件卸载时声音可能还未完成加载,直接执行
unloadAsync导致实例不存在报错。
修改后代码
import { Audio } from 'expo-av'; import { runOnUI } from 'expo-modules-core'; useEffect(() => { const sound = new Audio.Sound(); let isSoundLoaded = false; const loadAndPlaySound = async () => { try { await sound.loadAsync(require('../../sounds/app_notification.mp3')); isSoundLoaded = true; await sound.playAsync(); console.log('Sound played successfully'); } catch (error) { console.error('Error loading or playing sound:', error); } }; loadAndPlaySound(); return () => { // 强制在主线程执行卸载逻辑 runOnUI(async () => { if (isSoundLoaded) { try { await sound.unloadAsync(); console.log('Sound unloaded successfully'); } catch (error) { console.error('Error unloading sound:', error); } } })(); }; }, []);
关键改动说明
- 使用
runOnUI将卸载逻辑切换到主线程,解决线程不匹配问题; - 添加
isSoundLoaded状态标记,仅在声音成功加载后执行卸载,避免实例不存在的错误。
内容的提问来源于stack exchange,提问作者sparkey
相关产品推荐
相关产品推荐

