如何在初始化Supabase前检测Flutter应用的网络连接?
针对Flutter网络检测与初始化矛盾的解决方案
直接把网络检测放main开头可行,但要配套容错逻辑
可以在main函数最开头加网络检测,但不能只做检测就直接终止流程——毕竟网络状态可能是临时波动,而且Web和Android的检测方式需要兼容:
- Android端用
connectivity_plus包检测网络类型,Web端可以直接用Navigator.onLine判断(注意Web端这个API只能检测设备是否连上网,无法判断网络是否能访问互联网) - 检测后如果无网,不要直接抛出错误退出,而是先启动一个极简的无网提示页,给用户重试或退出的选项;如果有网,再执行后续的Supabase等初始化操作。
示例代码调整:
void main() async { WidgetsFlutterBinding.ensureInitialized(); final aPrefs = await SharedPreferences.getInstance(); // 先做网络检测 bool hasNetwork = await checkNetwork(); if (!hasNetwork) { // 无网时先启动提示页 runApp( ProviderScope( overrides: [sharedPrefsProvider.overrideWithValue(aPrefs)], child: const NoNetworkPage(), ), ); return; } // 有网时执行初始化,加异常捕获处理中途断网情况 try { await SupabaseUtil.init(); await GdSubscriptionService.init(); } catch (e) { // 初始化失败,跳转错误提示页 runApp( ProviderScope( overrides: [sharedPrefsProvider.overrideWithValue(aPrefs)], child: const InitFailedPage(), ), ); return; } // 初始化成功,启动主App runApp( ProviderScope( overrides: [sharedPrefsProvider.overrideWithValue(aPrefs)], child: const MyApp(), ), ); } // 兼容Web和Android的网络检测方法 Future<bool> checkNetwork() async { if (kIsWeb) { return Navigator.onLine; } else { final connectivityResult = await Connectivity().checkConnectivity(); return connectivityResult != ConnectivityResult.none; } }
更优的方案:把初始化移到UI层做,配合全局网络监听
直接在main里做检测的缺点是缺乏灵活的UI反馈(比如加载动画、重试按钮),更合理的做法是:
- main函数只做必要的本地初始化(比如SharedPreferences),直接启动App
- 在启动页(SplashScreen)里完成网络检测、Supabase初始化逻辑,同时展示加载状态、无网提示
- 用
connectivity_plus监听网络状态变化,一旦网络恢复,自动触发初始化重试
示例启动页逻辑:
class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State<SplashScreen> createState() => _SplashScreenState(); } class _SplashScreenState extends State<SplashScreen> { bool _isLoading = false; bool _showError = false; @override void initState() { super.initState(); _initApp(); // 监听网络状态变化,恢复时自动重试 Connectivity().onConnectivityChanged.listen((result) { if (result != ConnectivityResult.none && _showError) { _initApp(); } }); } Future<void> _initApp() async { if (!mounted) return; setState(() { _isLoading = true; _showError = false; }); try { await SupabaseUtil.init(); await GdSubscriptionService.init(); // 初始化成功,跳转首页 if (mounted) { Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const HomePage())); } } catch (e) { if (mounted) setState(() => _showError = true); } finally { if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: _isLoading ? const CircularProgressIndicator() : _showError ? Column( mainAxisSize: MainAxisSize.min, children: [ const Text("网络异常,请检查后重试"), const SizedBox(height: 16), ElevatedButton(onPressed: _initApp, child: const Text("重试")) ], ) : const SizedBox(), ), ); } }
关键注意点
- 不要依赖单次网络检测:网络状态是动态变化的,必须配合异常捕获和状态监听
- Web端
Navigator.onLine有局限性:如果要判断是否能访问互联网,可以加一个简单的ping请求(比如请求某个可靠的公开API接口) - 初始化操作加超时:给Supabase这类依赖网络的初始化设置超时时间,避免长时间卡住
内容的提问来源于stack exchange,提问作者Davout
相关产品推荐
相关产品推荐

