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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 04:55:23