当用户离开我的页面时,我无法取消 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>
);
}
};