Flutter中如何为每个页面统一检测网络连接?
全局网络状态检测与离线横幅实现方案
核心思路
用单例类统一管理网络状态订阅,全局广播状态变化,再通过全局Widget挂载离线横幅,彻底避免每个页面重复订阅和代码冗余问题。
步骤1:实现全局网络状态管理单例
创建单例类负责订阅网络变化、校验真实联网状态,并对外暴露状态流,确保全App只有一份订阅:
import 'dart:async'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:internet_connection_checker/internet_connection_checker.dart'; class NetworkManager { static final NetworkManager _instance = NetworkManager._internal(); factory NetworkManager() => _instance; NetworkManager._internal(); final Connectivity _connectivity = Connectivity(); final InternetConnectionChecker _connectionChecker = InternetConnectionChecker(); late StreamSubscription<ConnectivityResult> _connectivitySubscription; final StreamController<bool> _networkStatusController = StreamController<bool>.broadcast(); Stream<bool> get networkStatusStream => _networkStatusController.stream; bool _isConnected = true; void initialize() async { // 初始化当前联网状态 _isConnected = await _connectionChecker.hasConnection; _networkStatusController.add(_isConnected); // 订阅系统连接状态变化 _connectivitySubscription = _connectivity.onConnectivityChanged.listen((result) async { await _checkRealConnection(); }); // 离线时定时重试检测,解决自动重连问题 _startOfflineRetryTimer(); } Future<void> _checkRealConnection() async { bool newStatus = await _connectionChecker.hasConnection; if (newStatus != _isConnected) { _isConnected = newStatus; _networkStatusController.add(_isConnected); } } void _startOfflineRetryTimer() { Timer.periodic(const Duration(seconds: 5), (timer) { if (!_isConnected) _checkRealConnection(); }); } void dispose() { _connectivitySubscription.cancel(); _networkStatusController.close(); } }
步骤2:全局挂载离线横幅
在MaterialApp的builder中添加全局监听,统一显示离线横幅,无需每个页面单独编写逻辑:
import 'package:flutter/material.dart'; void main() { final networkManager = NetworkManager(); networkManager.initialize(); runApp(MyApp(networkManager: networkManager)); } class MyApp extends StatelessWidget { final NetworkManager networkManager; const MyApp({super.key, required this.networkManager}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Network Demo', builder: (context, child) { return StreamBuilder<bool>( stream: networkManager.networkStatusStream, initialData: true, builder: (context, snapshot) { bool isConnected = snapshot.data ?? true; return Column( children: [ // 仅离线时显示顶部横幅 if (!isConnected) Container( width: double.infinity, color: Colors.redAccent, padding: const EdgeInsets.symmetric(vertical: 8), child: const Text( '您已离线', textAlign: TextAlign.center, style: TextStyle(color: Colors.white), ), ), // 主页面内容区域 Expanded(child: child ?? const SizedBox()), ], ); }, ); }, home: const HomePage(), ); } }
步骤3:资源释放
在App退出时调用dispose释放订阅和控制器,避免内存泄漏:
// 将MyApp改为StatefulWidget后,在dispose中处理 @override void dispose() { networkManager.dispose(); super.dispose(); }
解决的核心问题
- 消除重复订阅:单例类仅维护一份网络订阅,全App共享状态流
- 自动重连检测:离线状态下定时重试联网校验,无需手动触发
- 全局统一渲染:离线横幅由MaterialApp统一管理,无需在每个页面复制代码
内容的提问来源于stack exchange,提问作者Risheek Mittal
相关产品推荐
相关产品推荐

