Flutter Web返回按钮未触发dispose,视频后台持续播放问题求助
解决Flutter Web + auto_route页面返回后视频继续播放的问题
核心原因
- auto_route在Web端的路由机制下,
WillPopScope的onWillPop无法拦截浏览器的返回事件 - 页面未触发
dispose大概率是路由配置中开启了keepAlive: true,页面被缓存导致不会销毁
可行解决方案
方案一:利用AutoRouteAware监听页面生命周期
auto_route提供了AutoRouteAware mixin,可监听页面的路由进入/离开事件,替代WillPopScope和依赖dispose的逻辑:
class VideoPage extends StatefulWidget { const VideoPage({super.key}); @override State<VideoPage> createState() => _VideoPageState(); } class _VideoPageState extends State<VideoPage> with AutoRouteAware { late VideoPlayerController _videoController; late AutoRouteObserver _routeObserver; @override void didChangeDependencies() { super.didChangeDependencies(); // 注册路由观察者 _routeObserver = AutoRouter.of(context).routeObserver; _routeObserver.subscribe(this, AutoRouter.of(context).currentRoute!); } @override void initState() { super.initState(); // 初始化视频播放器 _videoController = VideoPlayerController.networkUrl(Uri.parse("你的视频地址")) ..initialize().then((_) { setState(() {}); _videoController.play(); }); } @override void didPop() { // 页面被弹出(点击返回)时触发,停止播放并释放资源 _videoController.pause(); _videoController.dispose(); super.didPop(); } @override void dispose() { _routeObserver.unsubscribe(this); // 双重保险,防止页面被销毁时未处理 if (_videoController.value.isInitialized) { _videoController.dispose(); } super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: _videoController.value.isInitialized ? VideoPlayer(_videoController) : const Center(child: CircularProgressIndicator()), ); } }
方案二:全局路由观察者拦截返回事件
如果需要多个页面统一处理,可自定义AutoRouteObserver全局监听路由pop事件:
class VideoRouteObserver extends AutoRouteObserver { @override void didPop(Route route, Route? previousRoute) { super.didPop(route, previousRoute); // 判断当前弹出的页面是视频页面(根据路由名称) if (route.settings.name == Routes.videoPage.name) { // 获取页面实例,调用停止播放方法 if (route is PageRoute && route.child is VideoPage) { final videoPage = route.child as VideoPage; // 需在VideoPage中提供公开的停止方法 videoPage.stopVideo(); } } } }
然后在初始化AutoRouter时添加该观察者:
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp.router( routerDelegate: AutoRouterDelegate( _appRouter, observers: [VideoRouteObserver()], // 添加自定义观察者 ), routeInformationParser: _appRouter.defaultRouteParser(), ); } final _appRouter = AppRouter(); }
额外注意点
- 检查路由配置,如果设置了
keepAlive: true,页面会被缓存,dispose永远不会触发,必须通过上述路由生命周期钩子处理资源释放 - 确保页面跳转使用auto_route的API(如
context.pushRoute(VideoRoute())),而非原生Navigator.push,否则路由事件无法被auto_route的观察者捕获
内容的提问来源于stack exchange,提问作者PortalGamesMais
相关产品推荐
相关产品推荐

