flutter_subtitle_wrapper
flutter_subtitle_wrapper copied to clipboard
fix: StateError (Bad state: Cannot add new events after calling close)
Description A clear and concise description of what the bug is.
Steps To Reproduce
- 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!),
),
)
- Navigate to a second screen:
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => VideoPlayerFullScreen(
controller: videoController,
subtitleController: subtitleController,
),
),
);
- 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),
),
)
- 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();
}