You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用react-native-sounds实现单按钮播放暂停切换及场景暂停的音乐播放器?

解决react-native-sounds播放器的两个核心问题

一、修复同一按钮切换播放/暂停失效

问题根源在于你可能依赖了sound实例的实时状态(比如sound.isPlaying()),但播放/暂停是异步操作,状态同步会有延迟。正确的做法是用组件state主动维护播放状态:

  1. 用useState维护播放状态,useRef保存sound实例(避免组件重渲染时重新创建):
import Sound from 'react-native-sound';
import { useState, useRef, useEffect } from 'react';
import { TouchableOpacity, Text } from 'react-native';

const MusicPlayer = () => {
  const [isPlaying, setIsPlaying] = useState(false);
  const soundRef = useRef(null);

  // 初始化sound实例
  useEffect(() => {
    Sound.setCategory('Playback'); // 确保音频类别正确
    const sound = new Sound('your-audio-file.mp3', Sound.MAIN_BUNDLE, (error) => {
      if (error) console.log('音频加载失败', error);
    });
    soundRef.current = sound;

    // 组件卸载时释放资源
    return () => {
      if (soundRef.current) {
        soundRef.current.stop();
        soundRef.current.release();
      }
    };
  }, []);

  // 播放/暂停切换逻辑
  const togglePlayPause = async () => {
    const sound = soundRef.current;
    if (!sound) return;

    if (isPlaying) {
      await sound.pause();
      setIsPlaying(false);
    } else {
      await sound.play((success) => {
        if (!success) {
          console.log('播放失败');
          setIsPlaying(false);
        } else {
          // 播放结束后重置状态
          setIsPlaying(false);
        }
      });
      setIsPlaying(true);
    }
  };

  return (
    <TouchableOpacity onPress={togglePlayPause}>
      <Text>{isPlaying ? '暂停' : '播放'}</Text>
    </TouchableOpacity>
  );
};

关键注意点:

  • 用useRef存储sound实例,确保组件重渲染时不会丢失引用
  • 切换操作直接根据isPlaying state执行,而非依赖sound.isPlaying()(该方法返回值可能与实际状态不同步)
  • 在播放回调中处理失败和播放完成的状态重置

二、实现切换曲目/离开页面自动暂停

1. 切换曲目时自动暂停

加载新曲目时,先停止当前音频,再初始化新实例:

const loadNewTrack = (trackPath) => {
  const currentSound = soundRef.current;
  if (currentSound) {
    currentSound.stop();
    currentSound.release();
  }

  const newSound = new Sound(trackPath, Sound.MAIN_BUNDLE, (error) => {
    if (error) console.log('新曲目加载失败', error);
  });
  soundRef.current = newSound;
  setIsPlaying(false); // 切换曲目后重置播放状态
};

2. 离开页面时自动暂停

利用useEffect清理函数处理组件卸载场景;如果用react-navigation,还可监听页面焦点事件,失去焦点时暂停:

import { useFocusEffect } from '@react-navigation/native';

useFocusEffect(
  React.useCallback(() => {
    // 页面获得焦点时的操作(可选)
    return () => {
      // 页面失去焦点时暂停播放
      const sound = soundRef.current;
      if (sound && isPlaying) {
        sound.pause();
        setIsPlaying(false);
      }
    };
  }, [isPlaying])
);

常见坑点排查

  • 确保音频文件路径正确,必须等待加载完成后再执行播放
  • 禁止在每次渲染时重新创建Sound实例,必须用useRef持久化存储
  • 播放完成后务必重置isPlaying状态,避免按钮状态与实际播放状态不符

内容的提问来源于stack exchange,提问作者ABHISHEK NAMBIAR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:15:37