flutter_subtitle_wrapper icon indicating copy to clipboard operation
flutter_subtitle_wrapper copied to clipboard

fix: StateError (Bad state: Cannot add new events after calling close)

Open SX-Code opened this issue 6 months ago • 0 comments

Description A clear and concise description of what the bug is.

Steps To Reproduce

  1. First screen:

// controller
VideoPlayerController _controller = VideoPlayerController.networkUrl(
  Uri.parse(url),
  videoPlayerOptions: VideoPlayerOptions(
    allowBackgroundPlayback: true,
  ),
);

SubtitleController _subtitleController = SubtitleController(
  subtitleUrl: subtitle,
  subtitleType: SubtitleType.srt,
);

// use
SubtitleWrapper(
  videoPlayerController: _controller!,
  subtitleController: _subtitleController!,
  subtitleStyle: const SubtitleStyle(
    textColor: Colors.white,
    hasBorder: true,
  ),
  videoChild: AspectRatio(
    aspectRatio: _controller!.value.aspectRatio,
    child: VideoPlayer(_controller!),
  ),
)


  1. Navigate to a second screen:
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (_) => VideoPlayerFullScreen(
      controller: videoController,
      subtitleController: subtitleController,
    ),
  ),
);

  1. Second screen:
SubtitleWrapper(
  videoPlayerController: widget.controller,
  subtitleController: widget.subtitleController!,
  subtitleStyle: const SubtitleStyle(
    textColor: Colors.white,
    hasBorder: true,
  ),
  videoChild: AspectRatio(
    aspectRatio: widget.controller.value.aspectRatio,
    child: VideoPlayer(widget.controller),
  ),
)

  1. See error
StateError (Bad state: Cannot add new events after calling close)

Solution Remove the listener in a timely manner: lib/bloc/subtitle/subtitle_bloc.dart

void _listener() {
  final videoPlayerPosition = videoPlayerController.value.position;
  if (subtitles.subtitles.isNotEmpty &&
      videoPlayerPosition.inMilliseconds >
          subtitles.subtitles.last.endTime.inMilliseconds) {
    add(CompletedShowingSubtitles());
  }
  for (final subtitleItem in subtitles.subtitles) {
    final validStartTime = videoPlayerPosition.inMilliseconds >
        subtitleItem.startTime.inMilliseconds;
    final validEndTime = videoPlayerPosition.inMilliseconds <
        subtitleItem.endTime.inMilliseconds;
    final subtitle = validStartTime && validEndTime ? subtitleItem : null;
    if (validStartTime && validEndTime && subtitle != _currentSubtitle) {
      _currentSubtitle = subtitle;
    } else if (!_currentSubtitleIsValid(
      videoPlayerPosition: videoPlayerPosition.inMilliseconds,
    )) {
      _currentSubtitle = null;
    }
    add(
      UpdateLoadedSubtitle(
        subtitle: _currentSubtitle,
      ),
    );
  }
}

Future<void> loadSubtitle({
  required Emitter<SubtitleState> emit,
}) async {
  emit(LoadingSubtitle());
  videoPlayerController.addListener(_listener);
}

@override
Future<void> close() {
  subtitleController.detach();
  // remove listener
  videoPlayerController.removeListener(_listener);
  return super.close();
}

SX-Code avatar Aug 17 '24 19:08 SX-Code