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

如何实现React Native中音频互斥播放:点击新音频时停止旧音频

解决Expo React Native多音频同时播放问题

问题核心在于每个SoundPlayer组件独立维护自身的音频实例,互相无法感知对方的播放状态,导致多个音频同时播放。以下是两种可行的解决方案:

方案一:状态提升到父组件(简单场景适用)

将音频播放的控制逻辑统一放到父组件中,由父组件维护当前播放的音频实例,确保同一时间仅一个音频播放。

1. 修改父组件,统一管理音频播放

import React, { useState } from 'react';
import { Audio } from 'expo-av';
import SoundPlayer from './SoundPlayer';
import English from './English';
import NoteDesc from './NoteDesc';

export default function YourParentComponent({ route }) {
  const [currentPlayingSound, setCurrentPlayingSound] = useState(null);

  const handlePlaySound = async (voice) => {
    // 停止并卸载当前播放的音频
    if (currentPlayingSound) {
      await currentPlayingSound.stopAsync();
      await currentPlayingSound.unloadAsync();
    }

    // 创建新音频实例并播放
    const { sound: newSound } = await Audio.Sound.createAsync(voice);
    setCurrentPlayingSound(newSound);
    await newSound.playAsync();

    // 监听播放结束,自动清理状态
    newSound.setOnPlaybackStatusUpdate((status) => {
      if (status.didJustFinish) {
        setCurrentPlayingSound(null);
        newSound.unloadAsync();
      }
    });
  };

  return (
    <>
      <SoundPlayer onPlay={() => handlePlaySound(route.params.voice)}>
        <English English={route.params.English} />
      </SoundPlayer>

      <SoundPlayer onPlay={() => handlePlaySound(route.params.voice2)}>
        <NoteDesc noteDesc={route.params.noteDesc} />
      </SoundPlayer>
    </>
  );
}

2. 简化SoundPlayer组件

去掉内部的音频处理逻辑,仅负责触发父组件传递的播放回调:

import React from "react";
import { TouchableOpacity, StyleSheet, View } from "react-native";

export default function SoundPlayer({ onPlay, children }) {
  return (
    <View>
      <TouchableOpacity onPress={onPlay}>{children}</TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {},
  English: {
    color: "snow",
    fontSize: 30,
    textAlign: "center",
  },
});

方案二:使用Context全局管理音频(复杂场景适用)

当应用中有多个音频播放组件,需要跨组件统一控制时,使用React Context更灵活。

1. 创建音频Context

// AudioContext.js
import React, { createContext, useState, useContext } from 'react';
import { Audio } from 'expo-av';

const AudioContext = createContext();

export function AudioProvider({ children }) {
  const [currentSound, setCurrentSound] = useState(null);

  const playSound = async (voice) => {
    // 停止当前音频
    if (currentSound) {
      await currentSound.stopAsync();
      await currentSound.unloadAsync();
    }

    // 创建并播放新音频
    const { sound: newSound } = await Audio.Sound.createAsync(voice);
    setCurrentSound(newSound);
    await newSound.playAsync();

    // 播放结束自动清理
    newSound.setOnPlaybackStatusUpdate((status) => {
      if (status.didJustFinish) {
        setCurrentSound(null);
        newSound.unloadAsync();
      }
    });
  };

  return (
    <AudioContext.Provider value={{ playSound }}>
      {children}
    </AudioContext.Provider>
  );
}

export function useAudio() {
  return useContext(AudioContext);
}

2. 在应用根组件包裹AudioProvider

// App.js
import { AudioProvider } from './AudioContext';
import YourParentComponent from './YourParentComponent';

export default function App() {
  return (
    <AudioProvider>
      <YourParentComponent />
    </AudioProvider>
  );
}

3. 修改SoundPlayer组件使用Context

import React from "react";
import { TouchableOpacity, StyleSheet, View } from "react-native";
import { useAudio } from './AudioContext';

export default function SoundPlayer({ voice, children }) {
  const { playSound } = useAudio();

  const handlePlay = () => {
    playSound(voice);
  };

  return (
    <View>
      <TouchableOpacity onPress={handlePlay}>{children}</TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {},
  English: {
    color: "snow",
    fontSize: 30,
    textAlign: "center",
  },
});

4. 父组件恢复原写法

无需额外修改,直接使用原组件结构即可:

<SoundPlayer voice={route.params.voice}>
  <English English={route.params.English} />
</SoundPlayer>

<SoundPlayer voice={route.params.voice2}>
  <NoteDesc noteDesc={route.params.noteDesc} />
</SoundPlayer>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 01:10:02