Flutter如何高效实现无间断自动顺序播放视频?onComplete仅触发一次
问题根因
- 你的
MyVideoPlayer仅在首次初始化时给controller绑定了播放完成监听,后续_playVideo方法每次创建新的VideoPlayerController实例后,没有给新实例绑定对应完成监听,因此后续视频播放结束后不会触发onComplete回调 - 旧
controller没有执行销毁操作,存在内存泄漏风险,同时冗余的重复监听逻辑也可能引发状态判断冲突
修复方案
- 调整
MyVideoPlayer的实现,将controller作为入参传入,同时在didUpdateWidget生命周期中处理controller更新后的监听重新绑定,增加销毁逻辑释放资源
class MyVideoPlayer extends StatefulWidget { const MyVideoPlayer({ Key? key, required this.controller, required this.onComplete, }) : super(key: key); final VideoPlayerController controller; final VoidCallback onComplete; @override MyVideoPlayerState createState() => MyVideoPlayerState(); } class MyVideoPlayerState extends State<MyVideoPlayer> { late VoidCallback _listener; @override void initState() { super.initState(); _bindListener(); } @override void didUpdateWidget(covariant MyVideoPlayer oldWidget) { super.didUpdateWidget(oldWidget); // controller更新时解绑旧监听,绑定新监听 if (oldWidget.controller != widget.controller) { oldWidget.controller.removeListener(_listener); _bindListener(); } } void _bindListener() { _listener = () { final value = widget.controller.value; if (!value.isPlaying && value.position >= value.duration) { widget.onComplete(); } }; widget.controller.addListener(_listener); } @override void dispose() { widget.controller.removeListener(_listener); super.dispose(); } @override Widget build(BuildContext context) { return VideoPlayer(widget.controller); } }
- 调整主逻辑,维护播放列表索引,播放下一个视频前先销毁旧的controller,避免资源泄漏
// 示例为StatefulWidget的主页面,需要维护播放列表、当前索引、controller状态 class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { // 替换为你的实际视频资源列表 final List<String> _videoAssets = ['video1.mp4', 'video2.mp4', 'video3.mp4']; int _currentIndex = 0; VideoPlayerController? _controller; @override void initState() { super.initState(); _playCurrentVideo(); } @override void dispose() { _controller?.dispose(); super.dispose(); } void _playCurrentVideo() { if (_currentIndex >= _videoAssets.length) return; // 全部播放完成的逻辑可自行补充 // 先销毁旧controller释放资源 _controller?.dispose(); // 创建新controller _controller = VideoPlayerController.asset(_videoAssets[_currentIndex]); // 初始化完成后自动播放 _controller!.initialize().then((_) { if (mounted) { setState(() {}); _controller!.play(); } }); } @override Widget build(BuildContext context) { if (_controller == null || !_controller!.value.isInitialized) { return const SizedBox(); // 加载占位组件可自行替换 } return MyVideoPlayer( controller: _controller!, onComplete: () { // 播放完成后索引+1,播放下一个视频 _currentIndex++; _playCurrentVideo(); if (mounted) setState(() {}); }, ); } }
优化说明
- 修正后每次更换视频都会给新的controller绑定播放完成监听,确保每个视频播放结束都会触发回调实现连续播放
- 增加了controller的销毁逻辑,避免内存泄漏
- 移除了冗余的重复监听逻辑,状态判断改为直接对比
position和duration,避免了取整误差导致的判断失效问题
内容的提问来源于stack exchange,提问作者userRM
相关产品推荐
相关产品推荐

