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

在React Native中如何按顺序连续播放数组内的音频轨道?

React Native 音频数组顺序连续播放解决方案

你现有代码无法连续播放的核心原因有两个:

  1. Sound 实例仅在组件首次渲染时初始化了一次,后续 id 变更不会自动创建新的音频实例加载对应文件
  2. 第一个音频播放完成后触发 setId 更新,没有自动触发新音频的加载和播放逻辑

修复后的可运行代码

import { useState, useEffect, useRef } from 'react';
import { View, Image, TouchableOpacity } from 'react-native';
import Sound from 'react-native-sound';

Sound.setCategory('Playback');

const AudioPlayer = () => {
  // 替换为实际的音频总数量
  const TOTAL_AUDIO_COUNT = 10;
  const [id, setId] = useState(1);
  // 用ref存储音频实例和播放状态,避免渲染丢失
  const soundRef = useRef(null);
  const isPlayingRef = useRef(false);

  // 监听id变化,自动加载对应音频并播放
  useEffect(() => {
    // 超出音频总数停止播放
    if (id > TOTAL_AUDIO_COUNT) {
      isPlayingRef.current = false;
      return;
    }

    // 销毁旧实例释放内存
    if (soundRef.current) {
      soundRef.current.release();
    }

    // 初始化新音频实例
    const newSound = new Sound(`/data/user/0/com.hay/cache/${id}.mp3`, Sound.MAIN_BUNDLE, (error) => {
      if (error) {
        console.log('音频加载失败:', error);
        // 加载失败自动跳转下一个
        setId(prev => prev + 1);
        return;
      }
      // 加载完成自动播放
      newSound.play((success) => {
        if (!success) {
          console.log('播放失败');
        }
        // 播放结束后自动跳转下一个
        setId(prev => prev + 1);
      });
    });

    soundRef.current = newSound;
    isPlayingRef.current = true;

    // 组件卸载或id变化前销毁实例,避免内存泄漏
    return () => {
      if (soundRef.current) {
        soundRef.current.stop();
        soundRef.current.release();
      }
    };
  }, [id]);

  const playA = () => {
    // 避免重复触发播放
    if (isPlayingRef.current) return;
    // 从第一个音频开始播放
    setId(1);
  };

  return (
    <View style={{flex: 1, backgroundColor: '#FFEDCB', justifyContent: 'center'}}>
      <View style={{alignSelf: 'center'}} >
        <Image source={globo} style={{width: 340, height: 484}} />
        <View style={{ position: 'absolute', top: 403 }}>
          <View style={{flexDirection: 'row',position: 'absolute', right: -120 }}>
            <TouchableOpacity onPress={playA} style={styles.iconHeart}>
              <Icon name={'play-circle-outline'} size={60} color='#F8C56A' />
            </TouchableOpacity>
          </View>
        </View>
      </View>
    </View>
  );
};

核心逻辑说明

  • 用useRef存储音频实例和播放状态,避免组件重新渲染导致实例丢失、重复触发播放
  • 通过useEffect监听播放id的变化,每次id更新时先销毁旧音频实例,再加载新的音频文件自动播放
  • 音频播放完成的回调中更新id,自动触发下一个音频的加载播放流程
  • 增加了边界判断,音频全部播放完成后自动停止,不会无限自增id

注意事项

  • 把代码中的TOTAL_AUDIO_COUNT替换为你实际的音频总数
  • 如果你的音频路径不是固定数字命名规则,可以把id换成音频路径数组的下标,遍历数组播放即可
  • 可根据需求自行扩展暂停、停止的控制逻辑,直接调用soundRef.current对应的暂停、停止方法即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:57:00