[英]Expo AV playback callback strange behaviour with state properties
我開始用這個 go 堅果。 我正在錄制音頻,一旦我停止錄制作為此過程的一部分,我還會加載音頻,以便在必要時可以播放它,在這里我執行setOnPlaybackStatusUpdate
。 我使用播放回調,以便可以根據positionMillis
更新我的currentSeconds
state 。
問題是我得到的currentSeconds
和recordedDuration
state 值。 它們的值如何在觸發音頻播放的playAudio
方法和作為回調方法的onPlaybackStatusUpdate
之間發生變化?
當我在控制台中使用 output 時,它們在兩種方法中的值都是我期望它們相同時得到的:
In playAudio - currentSeconds: 0
In playAudio - recordedDuration: 4.5
In onPlaybackStatusUpdate - currentSeconds: 115.5
In onPlaybackStatusUpdate - recordedDuration: 0
這是代碼:
const AudioRecorder = useRef(new Audio.Recording());
const AudioPlayer = useRef(new Audio.Sound());
const timerMaxDuration = 120
const [currentSeconds, setCurrentSeconds] = useState<number>(timerMaxDuration);
const [recordedDuration, setRecordedDuration] = useState<number>(0);
const stopRecording = async () => {
try {
await AudioRecorder.current.stopAndUnloadAsync();
// To hear sound through speaker and not earpiece on iOS
await Audio.setAudioModeAsync({ allowsRecordingIOS: false });
const recordedURI = AudioRecorder.current.getURI();
SetRecordingURI(recordedURI)
AudioRecorder.current = new Audio.Recording();
send('STOP')
setRecordedDuration(+(timerMaxDuration - currentSeconds).toFixed(1)) // there is subtraction because during the recording there is a countdown from timerMaxDuration
setCurrentSeconds(0)
// Load audio after recording so that it is ready to be played
loadAudio(recordedURI)
} catch (error) {
console.log(error);
}
};
const loadAudio = async (recordedUri) => {
try {
const playerStatus = await AudioPlayer.current.getStatusAsync();
if (playerStatus.isLoaded === false) {
AudioPlayer.current.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate)
await AudioPlayer.current.loadAsync({ uri: recordedUri }, { progressUpdateIntervalMillis: 20 }, true)
}
} catch (error) {
console.log(error)
}
}
const playAudio = async () => {
console.log(`In playAudio - currentSeconds: ${currentSeconds}`)
console.log(`In playAudio - recordedDuration: ${recordedDuration}`)
try {
const playerStatus = await AudioPlayer.current.getStatusAsync();
if (playerStatus.isLoaded) {
if (playerStatus.isPlaying === false) {
AudioPlayer.current.playAsync();
send('PLAY')
}
}
} catch (error) {
console.log(error);
}
};
const onPlaybackStatusUpdate = playbackStatus => {
if (playbackStatus.isPlaying) {
console.log(`In onPlaybackStatusUpdate - currentSeconds: ${currentSeconds}`)
console.log(`In onPlaybackStatusUpdate - recordedDuration: ${recordedDuration}`)
if(currentSeconds >= recordedDuration){
stopAudio()
}
else{
setCurrentSeconds(+(playbackStatus.positionMillis / 1000).toFixed(1))
}
}
}
好的,所以播放回調沒有任何問題。 問題是兩個播放回調都是一個箭頭函數,這意味着在回調中唯一會改變的屬性值是參數playbackStatus
之一,其他屬性的值將保持與創建function時相同。
React 中的一個解決方法是通過以下方式使用 useEffect,它允許訪問 state 值currentSeconds
和recordedDuration
:
useEffect(() => {
if(currentSeconds >= recordedDuration)
stopAudio()
}, [currentSeconds]);
const onPlaybackStatusUpdate = playbackStatus => {
if (playbackStatus.isPlaying)
setCurrentSeconds(+(playbackStatus.positionMillis / 1000).toFixed(1))
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.