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

使用go_router时,Flutter错误重定向至主页存在bug

问题原因分析
  1. 重复触发跳转:ErrorStatelessView是无状态组件,每次build都会创建新的Timer,哪怕已经完成跳转,之前的Timer仍会执行,导致多次触发主页跳转;同时使用pushNamed会在路由栈中添加新页面而非替换当前错误页,路由栈堆积后操作时容易回到错误页,再次触发跳转循环。
  2. 全局错误处理设置不当:在MaterialApp的builder中每次设置ErrorWidget.builder,会导致每次页面重建都覆盖错误处理逻辑,可能引发不必要的错误页渲染。
  3. 错误状态未重置:当getSectionOffers返回错误状态时,跳转到主页后该状态仍未恢复,主页会再次渲染ErrorStatelessView,形成无限重定向循环。
解决方案

1. 修复错误页的跳转逻辑

将ErrorStatelessView改为有状态组件,确保Timer只执行一次,同时使用pushReplacementNamed替换当前路由,避免路由栈堆积:

class ErrorStatelessView extends StatefulWidget {
  const ErrorStatelessView({super.key});

  @override
  State<ErrorStatelessView> createState() => _ErrorStatelessViewState();
}

class _ErrorStatelessViewState extends State<ErrorStatelessView> {
  Timer? _redirectTimer;

  @override
  void initState() {
    super.initState();
    // 仅在组件初始化时创建一次Timer
    _redirectTimer = Timer(const Duration(seconds: 3), () {
      if (mounted) { // 确保组件仍挂载时再执行跳转
        context.pushReplacementNamed('home');
      }
    });
  }

  @override
  void dispose() {
    _redirectTimer?.cancel(); // 组件销毁时取消Timer,避免内存泄漏和无效跳转
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          SizedBox(height: 100, child: Image.asset('assets/images/oops.png')),
          const Text('Oops, it looks like something went wrong.'),
          const Text('You will be redirected back to the home'),
          const Text('page shortly.'),
        ],
      ),
    ));
  }
}

2. 正确设置全局错误处理

在main函数中全局设置ErrorWidget.builder,而非在MaterialApp的builder中重复设置:

void main() {
  // 全局设置错误Widget
  ErrorWidget.builder = (FlutterErrorDetails errorDetails) {
    // 此处可添加错误日志逻辑
    return const ErrorStatelessView();
  };
  
  runApp(const ProviderScope(child: MyApp()));
}

同时修改主页面代码,移除MaterialApp builder中的ErrorWidget.builder设置:

@override
Widget build(BuildContext context) {
  AsyncValue<HomeOffers> offers = ref.watch(getSectionOffers(sections));
  Size size = MediaQuery.of(context).size;
  return offers.when(
    loading: () => const FormattedProgressIndicator(),
    error: (error, stackTrace) => const ErrorStatelessView(),
    data: (data) {
      return MaterialApp(
        builder: (context, child) {
          return Scaffold(body: offersDisplay(data, size));
        },
        home: const Scaffold(/* 主页内容 */),
      );
    },
  );
}

3. 确保跳转后错误状态重置

在跳转到主页时,触发getSectionOffers重新获取数据,避免主页仍处于错误状态:

class _ErrorStatelessViewState extends State<ErrorStatelessView> {
  Timer? _redirectTimer;
  late final WidgetRef ref;

  @override
  void initState() {
    super.initState();
    ref = ProviderScope.containerOf(context);
    _redirectTimer = Timer(const Duration(seconds: 3), () {
      if (mounted) {
        // 重置getSectionOffers的状态,触发重新获取数据
        ref.invalidate(getSectionOffers);
        context.pushReplacementNamed('home');
      }
    });
  }

  // ... dispose和build方法不变
}
额外注意事项
  • 确保getSectionOffers Provider在被invalidate后能正确重新发起请求,恢复正常状态。
  • 可在ErrorWidget.builder和AsyncValue.error中添加错误日志逻辑,方便后续问题排查。

内容的提问来源于stack exchange,提问作者Jelkimantis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 13:52:45