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

Flutter全路由网络检测问题:恢复连接后路由加载异常

问题分析

你遇到的核心问题是:InternetConnectionWrapper 在网络恢复时可能触发了 MaterialApp 子树的重建,导致 initialRoute 的同步判断逻辑再次执行——而此时如果 userData 的状态没有实时更新,或者导航栈状态被重置,就会出现路由跳转错误。

解决方案

要实现「断网时显示提示、恢复后回到原活跃路由」的需求,需要从两个核心点调整:

  1. 将初始路由的异步判断逻辑从 MaterialApp 中剥离,避免重建时重复执行错误判断;
  2. 优化网络监听组件的实现,确保网络恢复时保留原导航栈状态。

步骤1:用启动页处理初始路由判断

创建一个启动页(SplashScreen),仅在APP首次启动时执行 SharedPrefs 检查和路由跳转,避免网络恢复时重复触发初始路由逻辑:

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

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    _navigateToInitialRoute();
  }

  Future<void> _navigateToInitialRoute() async {
    // 异步获取SharedPrefs中的userData(替换成你实际的读取逻辑)
    final userData = await _getUserDataFromSharedPrefs();
    String targetRoute;

    if (userData.isNotEmpty) {
      targetRoute = userData[userType_index] == "user" 
          ? entryPointRoute 
          : dashboardLauncherScreenRoute;
    } else {
      targetRoute = kIsWeb ? loginScreenRoute : onboardingScreenRoute;
    }

    // 确保组件未销毁时执行跳转,替换当前启动页
    if (mounted) {
      Navigator.pushReplacementNamed(context, targetRoute);
    }
  }

  // 模拟SharedPrefs读取方法,替换成你的实际实现
  Future<List<String>> _getUserDataFromSharedPrefs() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getStringList('userData') ?? [];
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: CircularProgressIndicator()),
    );
  }
}

步骤2:修改MaterialApp配置

将 initialRoute 设置为启动页,确保初始判断只执行一次:

return MaterialApp(
  debugShowCheckedModeBanner: false,
  builder: (_, child) => InternetConnectionWrapper(child: child!),
  title: 'X',
  theme: darkTheme(context),
  navigatorKey: navigatorKey,
  routes: {
    // 添加启动页路由
    '/splash': (context) => const SplashScreen(),
    // 原有路由保留
    entryPointRoute: (context) => const EntryPointScreen(),
    dashboardLauncherScreenRoute: (context) => const DashboardLauncherScreen(),
    loginScreenRoute: (context) => const LoginScreen(),
    onboardingScreenRoute: (context) => const OnboardingScreen(),
  },
  initialRoute: '/splash',
);

步骤3:优化InternetConnectionWrapper

调整网络监听组件的逻辑,断网时仅覆盖显示断页,网络恢复时直接恢复原导航栈,不重置路由:

class InternetConnectionWrapper extends StatefulWidget {
  final Widget child;
  const InternetConnectionWrapper({super.key, required this.child});

  @override
  State<InternetConnectionWrapper> createState() => _InternetConnectionWrapperState();
}

class _InternetConnectionWrapperState extends State<InternetConnectionWrapper> {
  bool _hasInternet = true;
  late StreamSubscription<ConnectivityResult> _connectivitySubscription;

  @override
  void initState() {
    super.initState();
    _checkInitialConnectivity();
    // 监听网络状态变化
    _connectivitySubscription = Connectivity().onConnectivityChanged.listen((result) {
      setState(() {
        _hasInternet = result != ConnectivityResult.none;
      });
    });
  }

  Future<void> _checkInitialConnectivity() async {
    final result = await Connectivity().checkConnectivity();
    setState(() {
      _hasInternet = result != ConnectivityResult.none;
    });
  }

  @override
  void dispose() {
    _connectivitySubscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!_hasInternet) {
      // 断网时显示提示页,不替换原导航栈
      return Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text("无网络连接,请检查网络设置"),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: _checkInitialConnectivity,
                child: const Text("重试连接"),
              ),
            ],
          ),
        ),
      );
    }
    // 网络正常时直接返回原页面树,保留导航栈状态
    return widget.child;
  }
}
关键说明
  • 启动页的异步判断仅在APP首次启动时执行,网络恢复时不会重新触发,避免了基于旧状态的错误跳转;
  • InternetConnectionWrapper 仅在断网时覆盖显示提示,网络恢复时直接恢复原导航栈,确保回到断网前的活跃路由;
  • 避免在 MaterialApp 的 initialRoute 中做异步状态判断,因为 initialRoute 是同步属性,异步数据未加载完成时会导致初始路由错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 02:42:38