Flutter中如何结合connectivity_plus与go_router实现网络连通性校验
问题分析与解决方案
首先你现有代码的核心问题是判断逻辑错误:result == ConnectivityResult.mobile && result == ConnectivityResult.wifi永远不会成立——一个网络状态不可能同时是移动数据和WiFi。正确的判断应该是检查状态是否为ConnectivityResult.none,或者用||判断是否为移动/WiFi/以太网等有效连接。
下面是更优的实现方案,以及如何集成到go_router中:
一、修正StreamBuilder实现(页面级校验)
如果仍想保留StreamBuilder的方式,先修正逻辑问题,同时添加初始状态避免页面闪烁:
body: StreamBuilder<ConnectivityResult>( stream: Connectivity().onConnectivityChanged, initialData: ConnectivityResult.none, // 设置初始状态 builder: (context, snapshot) { final currentStatus = snapshot.data ?? ConnectivityResult.none; // 只要不是无网络状态,就显示正常页面 if (currentStatus != ConnectivityResult.none) { return _pages[_currentIndex]; } else { return NOTConnected(); } }, ),
二、全局路由级校验(go_router集成方案)
更专业的做法是把网络校验逻辑放到路由层面,通过go_router的redirect和refreshListenable实现全局自动跳转,无需在每个页面单独处理。
1. 封装网络状态服务
先把网络检测逻辑抽成独立服务,方便全局复用:
import 'package:connectivity_plus/connectivity_plus.dart'; import 'dart:io'; class NetworkService { final Connectivity _connectivity = Connectivity(); late Stream<ConnectivityResult> networkStatusStream; NetworkService() { networkStatusStream = _connectivity.onConnectivityChanged; } // 获取当前网络状态 Future<ConnectivityResult> getCurrentStatus() async { return await _connectivity.checkConnectivity(); } // 可选:校验是否真的能访问互联网(避免连接了无网WiFi的情况) Future<bool> isInternetAccessible() async { try { final response = await InternetAddress.lookup('google.com'); return response.isNotEmpty && response[0].rawAddress.isNotEmpty; } on SocketException catch (_) { return false; } } }
2. 实现路由刷新监听器
创建一个监听器,当网络状态变化时通知go_router重新执行重定向逻辑:
import 'package:flutter/foundation.dart'; class NetworkRefreshNotifier extends ChangeNotifier { NetworkRefreshNotifier() { final networkService = NetworkService(); // 监听网络状态变化,触发路由刷新 networkService.networkStatusStream.listen((_) { notifyListeners(); }); } }
3. 配置go_router路由
在go_router中配置redirect和refreshListenable,实现全局网络校验:
final GoRouter router = GoRouter( routes: [ GoRoute( path: '/', builder: (context, state) => HomePage(), ), GoRoute( path: '/no-network', builder: (context, state) => NOTConnected(), ), // 其他业务路由... ], // 重定向逻辑 redirect: (context, state) async { final networkService = NetworkService(); final connectivityStatus = await networkService.getCurrentStatus(); final isNoNetworkPage = state.location == '/no-network'; // 无网络且不在无网络页面,重定向到无网络页 if (connectivityStatus == ConnectivityResult.none && !isNoNetworkPage) { return '/no-network'; } // 网络恢复且在无网络页,重定向回之前的页面或首页 if (connectivityStatus != ConnectivityResult.none && isNoNetworkPage) { return state.previousLocation ?? '/'; } return null; // 不执行重定向 }, // 监听网络状态变化,自动触发重定向 refreshListenable: NetworkRefreshNotifier(), );
三、补充说明
connectivity_plus只能检测设备是否连接了网络,无法判断网络是否能访问互联网,如果需要更严格的校验,可在redirect中调用isInternetAccessible()方法。- 若使用状态管理库(如Provider/Riverpod),可以将
NetworkService注入到全局,避免重复实例化。
内容的提问来源于stack exchange,提问作者Tanmay Patil
相关产品推荐
相关产品推荐

