React Native 世博会AV播放回调奇怪行为与状态属性

evrscar2  于 2023-04-12  发布在  React
关注(0)|答案(2)|浏览(87)

我开始疯狂地使用这一个。我正在录制音频,一旦我停止录制作为此过程的一部分,我也会加载音频,以便在必要时可以播放,这里我做了setOnPlaybackStatusUpdate。我使用回放回调,以便我可以基于positionMillis更新我的currentSeconds状态。
问题是我得到的currentSecondsrecordedDuration状态值。为什么它们的值在触发音频播放的playAudio方法和回调方法onPlaybackStatusUpdate之间变化?
当我在控制台中输出它们在两个方法中的值时,这是我期望它们相同时得到的结果:

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))
            }
        }
    }
oxcyiej7

oxcyiej71#

好了,回放回调函数没有任何问题。问题是回放回调函数是一个箭头函数,这意味着在回调函数中唯一会改变的属性值是参数playbackStatus,其他属性的值将保持与创建函数时相同。
在React中的一个方法是以以下方式使用useEffect,它允许访问状态值currentSecondsrecordedDuration

useEffect(() => {
        if(currentSeconds >= recordedDuration)
            stopAudio()
    }, [currentSeconds]);

    const onPlaybackStatusUpdate = playbackStatus => {
        if (playbackStatus.isPlaying)
            setCurrentSeconds(+(playbackStatus.positionMillis / 1000).toFixed(1))
    }
g52tjvyc

g52tjvyc2#

面对类似的问题,另一种解决方法是使用useRef钩子而不是状态将所需的值存储在refs中。

相关问题