Flutter如何等待网络连接状态?启动无网不弹窗及多页面适配疑问
网络连接检测问题排查与全页面适配方案
一、无网启动时弹窗不显示的解决
你的推测正确:Connectivity().onConnectivityChanged流仅在网络状态发生变化时触发回调,应用无网启动时没有状态变更动作,因此不会执行弹窗逻辑。解决思路是在监听流之前,主动检查一次当前网络状态。
修改后的完整代码如下:
class _HomePageState extends State<HomePage> { late StreamSubscription subscription; bool isDeviceConnected = false; bool isAlertSet = false; @override void initState() { super.initState(); getConnectivity(); } Future<void> getConnectivity() async { // 主动检查初始网络状态 isDeviceConnected = await InternetConnectionChecker().hasConnection; if (!isDeviceConnected && !isAlertSet) { showDialogBox(); setState(() => isAlertSet = true); } // 监听网络状态变化 subscription = Connectivity().onConnectivityChanged.listen( (ConnectivityResult result) async { isDeviceConnected = await InternetConnectionChecker().hasConnection; if (!isDeviceConnected && !isAlertSet) { showDialogBox(); setState(() => isAlertSet = true); } else if (isDeviceConnected && isAlertSet) { // 网络恢复时自动关闭弹窗(可选优化) Navigator.of(context).pop(); setState(() => isAlertSet = false); } }, ); } @override void dispose() { subscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold(/* 页面原有布局 */); } void showDialogBox() => showDialog( context: context, barrierDismissible: false, builder: (_) => AlertDialog( title: const Text("无网络连接"), content: const Text("请检查你的网络设置"), actions: [ TextButton( onPressed: () async { bool hasConnection = await InternetConnectionChecker().hasConnection; if (hasConnection) { Navigator.of(context).pop(); setState(() => isAlertSet = false); } }, child: const Text("重试"), ) ], ), ); }
核心改动:在getConnectivity方法开头主动调用网络检查接口,直接判断初始状态并触发弹窗逻辑,避免依赖状态变化的流回调。
二、当前实现无法确保所有页面生效
当前代码的网络监听逻辑绑定在HomePage的State中,存在两个致命问题:
- 当
HomePage被弹出栈(比如用Navigator.pushReplacement跳转页面),State会被销毁,监听订阅也会被取消,其他页面无法检测网络状态。 - 其他页面未嵌入相同监听逻辑,无法触发弹窗提示。
解决方案:全局网络状态管理
将网络检测逻辑抽成全局服务,结合状态管理(如ChangeNotifier+Provider)实现全页面统一监听:
1. 编写全局网络管理类
import 'package:flutter/material.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:internet_connection_checker/internet_connection_checker.dart'; class NetworkManager extends ChangeNotifier { late StreamSubscription _connectivitySubscription; bool isConnected = false; bool isAlertShown = false; NetworkManager() { _initNetworkListener(); } Future<void> _initNetworkListener() async { // 初始网络状态检查 isConnected = await InternetConnectionChecker().hasConnection; notifyListeners(); // 持续监听网络状态变化 _connectivitySubscription = Connectivity().onConnectivityChanged.listen( (result) async { isConnected = await InternetConnectionChecker().hasConnection; notifyListeners(); }, ); } @override void dispose() { _connectivitySubscription.cancel(); super.dispose(); } }
2. 在全局注入状态管理
void main() { runApp( ChangeNotifierProvider( create: (context) => NetworkManager(), child: const MyApp(), ), ); }
3. 在MaterialApp的builder中全局处理弹窗
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '网络检测示例', home: const HomePage(), builder: (context, child) { return Consumer<NetworkManager>( builder: (context, networkManager, child) { // 无网且未弹窗时触发提示 if (!networkManager.isConnected && !networkManager.isAlertShown) { WidgetsBinding.instance.addPostFrameCallback((_) { _showNoInternetDialog(context, networkManager); }); } // 网络恢复时关闭弹窗 else if (networkManager.isConnected && networkManager.isAlertShown) { Navigator.of(context, rootNavigator: true).pop(); networkManager.isAlertShown = false; } return child!; }, ); }, ); } void _showNoInternetDialog(BuildContext context, NetworkManager manager) { showDialog( context: context, barrierDismissible: false, useRootNavigator: true, builder: (_) => AlertDialog( title: const Text("无网络连接"), content: const Text("请检查你的网络设置"), actions: [ TextButton( onPressed: () async { bool hasConnection = await InternetConnectionChecker().hasConnection; if (hasConnection) { Navigator.of(context).pop(); manager.isAlertShown = false; } }, child: const Text("重试"), ) ], ), ); manager.isAlertShown = true; } }
该方案优势:
- 网络监听逻辑全局唯一,避免重复创建订阅浪费资源。
- 所有页面共享网络状态,弹窗在全局范围内触发,不受页面跳转影响。
内容的提问来源于stack exchange,提问作者krishnaacharyaa
相关产品推荐
相关产品推荐

