onPressed 의 로컬변수

pharmDev·2024년 11월 24일

Flutter: VideoPlayer의 seekTo 동작과 position 값 유지 여부


질문

Flutter에서 VideoPlayerController.seekTo()를 사용하여 동영상 재생 위치를 이동시키는 기능을 구현 중입니다. 아래 코드를 기준으로:

IconButton(
  color: Colors.white,
  onPressed: () {
    final currentPosition = videoPlayerController.value.position;

    Duration position = Duration();

    if (currentPosition.inSeconds > 3) {
      position = currentPosition - Duration(seconds: 3);
    }
    videoPlayerController.seekTo(position);
  },
)
  1. 4초에서 버튼을 누르면 3초 뒤로 이동해 position = 1초가 됩니다.
  2. 이후 1초 상태에서 다시 버튼을 누르면 동영상이 1초 상태 그대로 머무르지 않고 처음(0초)으로 이동합니다.
    왜 이런 동작이 발생하며, position 값이 유지되지 않는 이유는 무엇인가요?

답변

1. 원인 분석

  • position 값은 유지되지 않는다.
    • 이유는 position 변수가 onPressed 함수의 로컬 변수이기 때문입니다.
    • 로컬 변수는 함수 호출 시 생성되고, 함수 실행이 끝나면 스코프를 벗어나 사라집니다.
    • 따라서 4초에서 버튼을 눌러 position = 1초로 설정되더라도, 함수 실행이 종료되면 이 값은 더 이상 유지되지 않습니다.

2. 코드 동작 흐름

첫 번째 버튼 클릭 (4초 → 1초)

  • 현재 위치 (currentPosition): 4초.
  • 코드 실행:
    Duration position = Duration(); // 초기값: 0초
    if (currentPosition.inSeconds > 3) {
      position = currentPosition - Duration(seconds: 3);
    }
    videoPlayerController.seekTo(position); // position = 1초
  • 조건 4초 > 3true이므로:
    • position = 4초 - 3초 = 1초.
  • seekTo(position)이 호출되어 동영상이 1초로 이동합니다.

두 번째 버튼 클릭 (1초에서 다시 뒤로가기)

  • 현재 위치 (currentPosition): 1초.
  • 코드 실행:
    Duration position = Duration(); // 초기값: 0초
    if (currentPosition.inSeconds > 3) {
      position = currentPosition - Duration(seconds: 3);
    }
    videoPlayerController.seekTo(position); // position = 0초
  • 조건 1초 > 3false이므로:
    • position은 초기값인 0초로 유지됩니다.
  • seekTo(position)이 호출되어 동영상이 0초(처음)으로 이동합니다.

3. 문제 원인

  • position의 초기값이 항상 Duration.zero(0초)로 설정되기 때문에, 조건이 false인 경우 0초로 이동하게 됩니다.
  • position이 로컬 변수라 이전 값이 유지되지 않고, 버튼을 누를 때마다 새로 선언됩니다.

4. 해결 방법: position을 클래스 변수로 설정

position 값을 유지하려면 로컬 변수 대신 클래스 변수로 선언해야 합니다. 아래는 수정된 코드입니다:

수정 코드

class _VideoPlayerState extends State<_VideoPlayer> {
  late final VideoPlayerController videoPlayerController;
  Duration currentSeekPosition = Duration.zero; // 클래스 변수로 선언

  
  void initState() {
    super.initState();
    videoPlayerController = VideoPlayerController.file(File(widget.video.path))
      ..initialize().then((_) {
        setState(() {});
      });
  }

  
  Widget build(BuildContext context) {
    return IconButton(
      color: Colors.white,
      onPressed: () {
        final currentPosition = videoPlayerController.value.position;

        if (currentPosition.inSeconds > 3) {
          currentSeekPosition = currentPosition - Duration(seconds: 3);
        } else {
          currentSeekPosition = currentPosition; // 현재 위치 유지
        }

        videoPlayerController.seekTo(currentSeekPosition);
      },
      icon: const Icon(Icons.rotate_left),
    );
  }
}

5. 수정 후 동작

  1. 4초에서 버튼 클릭:

    • currentSeekPosition = 1초로 업데이트.
    • 동영상이 1초로 이동합니다.
  2. 1초에서 다시 버튼 클릭:

    • currentSeekPosition = 1초로 유지.
    • 동영상이 1초에 그대로 머뭅니다.

6. 결론

  • 현재 코드에서 position은 로컬 변수이기 때문에 값이 유지되지 않고, 조건을 만족하지 못하면 초기값(0초)으로 돌아갑니다.
  • 이를 해결하려면 position을 클래스 변수로 전환하여 값을 지속적으로 유지해야 합니다. 이렇게 하면 동영상이 의도한 대로 동작하게 됩니다! 🎉
profile
코딩을 배우는 초보

0개의 댓글