You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web返回按钮未触发dispose,视频后台持续播放问题求助

解决Flutter Web + auto_route页面返回后视频继续播放的问题

核心原因

  1. auto_route在Web端的路由机制下,WillPopScope的onWillPop无法拦截浏览器的返回事件
  2. 页面未触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 12:02:51