React Native / Firebase / Expo Audio-在下载开始并且用户离开页面后取消loadAsync

问题描述

当用户离开我的页面时,我无法取消loadAsync。我试图在useEffect上使用清除功能,但是由于soundObject还没有加载,因为soundObject等于null,所以会给我一个错误。当其他页面成为焦点时,我也尝试使用redux并添加soundObject.stopAsync,但是由于soundObject可能尚未设置,但不会取消,并且我会播放音频并且无法停止。这是我的“暂停/播放”按钮组件,在其中调用loadAsync。任何帮助将不胜感激。谢谢

更新至我的游戏暂停处理程序 即使我觉得有更好的方法,我也找到了解决方法。我现在正在调用Audio.setIsEnabledAsync(false);作为清理功能。

  //CLEANUP FUNCTION
  useEffect(() => {
    Audio.setIsEnabledAsync(true);
    return function cleanUp() {
      reference.putFile(props.audioFile).cancel();
      Audio.setIsEnabledAsync(false);
    };
  },[]);
import React,{ useState,useEffect } from "react";
import { TouchableOpacity } from "react-native";
import { useDispatch,useSelector } from "react-redux";

import storage from "@react-native-firebase/storage";
import { playPause,stopPlay } from "../../../store/actions/playerActions";
import { Audio } from "expo-av";
import SmallIndicator from "../Indicators/SmallIndicator";

import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
import { faPlay,faPause } from "@fortawesome/pro-light-svg-icons";
import Colors from "../../../constants/Colors";

const PlayPause = (props) => {
  const dispatch = useDispatch();

  // LOAD FROM FIREBASE VARIABLES
  let audioFile = props.audioFile;
  const reference = storage().ref(audioFile);
  let task = reference.getDownloadURL();

  //HOOKS
  const isPlaying = useSelector((state) => state.player.isPlaying);
  const [iconSwitch,setIconSwitch] = useState(faPlay);
  const [soundObject,setSoundObject] = useState(null);
  const [isLoading,setIsLoading] = useState(false);

  // LOAD AUDIO SETTINGS
  useEffect(() => {
    const audioSettings = async () => {
      try {
        await Audio.setAudioModeAsync({
          allowsRecordingIOS: false,interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,playsInSilentModeIOS: true,interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DUCK_OTHERS,shouldDuckAndroid: true,staysActiveInBackground: false,playThroughEarpieceAndroid: true,});
      } catch (e) {
        console.log(e);
      }
      audioSettings();
    };
  },[]);

  //CLEANUP FUNCTION
  useEffect(() => {
    Audio.setIsEnabledAsync(true);
    return function cleanUp() {
      reference.putFile(props.audioFile).cancel();
      Audio.setIsEnabledAsync(false);
    };
  },[]);

  // STOP PLAY ON PAGE EXIT
  useEffect(() => {
    ifPlaying();
  },[isPlaying]);

  const ifPlaying = async () => {
    if (isPlaying === false && soundObject != null) {
      await soundObject.stopAsync();
      await soundObject.unloadAsync();
      setSoundObject(null);
      setIconSwitch(faPlay);
    }
  };

  // PLAY PAUSE TOGGLE
  const handlePlayPause = async () => {
    setIsLoading(true);
    let uri = await task;

    //PLAY
    if (isPlaying === false && soundObject === null) {
      const soundObject = new Audio.Sound();
      await soundObject.loadAsync({ uri },isPlaying,true);
      setSoundObject(soundObject);
      soundObject.playAsync();
      dispatch(playPause(true));
      setIconSwitch(faPause);

      // PAUSE
    } else if (isPlaying === true && soundObject != null) {
      dispatch(playPause(false));
      setIconSwitch(faPlay);

      // STOP AND PLAY
    } else if (isPlaying === true && soundObject === null) {
      dispatch(stopPlay(true));
      dispatch(playPause(true));
      const soundObject = new Audio.Sound();
      const status = { shouldPlay: true };
      await soundObject.loadAsync({ uri },status,true);
      setSoundObject(soundObject);
      soundObject.playAsync();
      setIconSwitch(faPause);

      // RESUME PLAY
    } else if (isPlaying === false && soundObject != null) {
      dispatch(playPause(true));
      soundObject.playAsync();
      setIconSwitch(faPause);
    }
    setIsLoading(false);
  };

  console.log(isPlaying);

  if (isLoading) {
    return <SmallIndicator />;
  }

  return (
    <TouchableOpacity onPress={handlePlayPause}>
      <FontAwesomeIcon icon={iconSwitch} size={35} color={Colors.primary} />
    </TouchableOpacity>
  );
};

export default PlayPause;

PlayPause组件位于我的SongItem组件中,我不会添加不适用的代码。

const SongItem = (props) => {
  return (
    <View>
      <PurchaseModal
        visible={modalToggle}
        purchaseSelector={purchaseSelector}
        radio_props={LicenseData}
        onPress={modalToggleHandler}
      />
      <View>
        <Card>
          <BodyText>{props.items.name}</BodyText>
          <View style={styles.innerContainer}>
            <PlayPause audioFile={props.items.audio} />
            <TouchableOpacity onPress={cartPress}>
              <FontAwesomeIcon
                icon={iconSwitch}
                size={35}
                color={Colors.primary}
              />
            </TouchableOpacity>
          </View>
          <TouchableOpacity onPress={modalToggleHandler} style={toggleStyle}>
            <FontAwesomeIcon
              icon={faFileInvoice}
              size={35}
              color={Colors.primary}
            />
          </TouchableOpacity>
        </Card>
      </View>
    </View>
  );
};

SongItem位于我的SongScreen上。当我调用dispatch(stopPlay)时,我将isPlaying切换为false;

const SongScreen = (props) => {
  const filteredSongs = useSelector((state) => state.filter.filteredSongs);
  const { goBack } = props.navigation;
  const dispatch = useDispatch();
  const backPress = () => {
    dispatch(stopPlay());
    goBack();
  };

  useEffect(() => {
    props.navigation.addListener("didBlur",() => {
      dispatch(stopPlay());
    });
  });

    return (
      <Gradient>
        <FlatList
          removeClippedSubviews={false}
          windowSize={2}
          maxToRenderPerBatch={6}
          data={filteredSongs}
          keyExtractor={(item) => item.id.toString()}
          renderItem={(itemData) => <SongItem items={itemData.item} />}
        />
        <MainButton name={"Back"} onPress={backPress} />
      </Gradient>
    );
  }
};

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)