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

如何在Flutter应用中实现全局网络连接状态检测?

Flutter全局网络状态监听与离线警告实现方案

问题需求

需要实现以下功能:

  • 应用运行期间全局持续监听网络状态变化,直至退出
  • 当Wi-Fi和移动网络均关闭时,弹出离线警告弹窗
  • 项目基于Provider做状态管理,依赖internet_connection_checker和connectivity_plus包

现有代码

main.dart

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';
import 'package:test/page/error.dart';
import 'package:test/routes.dart';
import 'package:test/service/connection_manager.dart';
import 'package:test/service/firebase_service.dart';
import 'package:test/firebase_options.dart';
import 'package:test/globals.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';


Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  await FirebaseService().initNotifications();
  await FirebaseService().initFirebaseRemoteConfig();

  int mainCount = 1;

  try {
    await deviceManager.getCurrentLocation();
    print('Main() is executed for $mainCount time(s)');
    mainCount ++;
  } catch(e) {
      print('Error getting current location: $e');
      try {
        await deviceManager.getLastestLocation();
      } catch (e) {
        print('Error getting latest location: $e');
      }
    }


  FlutterError.onError = (FlutterErrorDetails details) {
    runApp(const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: AppErrorScreen(),
    ));
  };


  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => ConnectionManager()),
        ChangeNotifierProvider(create: (_) => Globals()),
      ],
      child: MyApp(),
    ),
  );
}



class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: AppRoute().route,
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,
      debugShowCheckedModeBanner: false,
    );
  }
}

connection.dart(ConnectionManager类)

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:connectivity_plus/connectivity_plus.dart';

class ConnectionManager with ChangeNotifier {
  final Connectivity _connectivity = Connectivity();
  bool _isConnected = false;
  late StreamSubscription<List<ConnectivityResult>> _subscription;

  bool get isConnected => _isConnected;

  ConnectionManager() {
    _subscription = _connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
    _checkInitialConnection();
  }

  Future<void> _checkInitialConnection() async {
    final List<ConnectivityResult> connectivityResult = await _connectivity.checkConnectivity();
    // await _updateConnectionStatus(connectivityResult);
  }

  Future<void> _updateConnectionStatus(List<ConnectivityResult> result) async {
    bool isConnected = false;

    if (result != ConnectivityResult.none) {
      try {
        final lookupResult = await InternetAddress.lookup('google.com');
        isConnected = lookupResult.isNotEmpty;
      } on SocketException catch (_) {
        isConnected = false;
      }
    }

    _isConnected = isConnected;
    notifyListeners();
  }
}

问题分析

现有代码存在以下问题:

  • _checkInitialConnection方法中注释了_updateConnectionStatus调用,导致应用启动时无法初始化网络状态
  • 缺少全局离线警告的触发逻辑,网络断开时不会弹出提示
  • 手动实现的网络连通性检测可以用internet_connection_checker简化
  • 未在ConnectionManager销毁时取消Stream订阅,存在内存泄漏风险

解决方案

1. 完善ConnectionManager类

结合internet_connection_checker优化网络检测逻辑,添加订阅清理:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';

class ConnectionManager with ChangeNotifier {
  final Connectivity _connectivity = Connectivity();
  final InternetConnectionChecker _connectionChecker = InternetConnectionChecker();
  bool _isConnected = false;
  late StreamSubscription<List<ConnectivityResult>> _connectivitySubscription;
  late StreamSubscription<bool> _connectionCheckerSubscription;

  bool get isConnected => _isConnected;

  ConnectionManager() {
    // 监听连接类型变化,触发实际网络连通性检测
    _connectivitySubscription = _connectivity.onConnectivityChanged.listen((_) {
      _connectionCheckerSubscription.cancel();
      _startConnectionChecker();
    });
    // 初始化网络检测
    _startConnectionChecker();
    _checkInitialConnection();
  }

  Future<void> _checkInitialConnection() async {
    _isConnected = await _connectionChecker.hasConnection;
    notifyListeners();
  }

  void _startConnectionChecker() {
    // 监听实际网络连通性状态
    _connectionCheckerSubscription = _connectionChecker.onStatusChange.listen((status) {
      final newStatus = status == InternetConnectionStatus.connected;
      if (_isConnected != newStatus) {
        _isConnected = newStatus;
        notifyListeners();
      }
    });
  }

  @override
  void dispose() {
    // 取消订阅,避免内存泄漏
    _connectivitySubscription.cancel();
    _connectionCheckerSubscription.cancel();
    super.dispose();
  }
}

2. 全局实现离线警告

修改MyApp为StatefulWidget,在根节点监听网络状态变化并触发弹窗:

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _hasShownOfflineDialog = false;

  @override
  Widget build(BuildContext context) {
    return Consumer<ConnectionManager>(
      builder: (context, connectionManager, child) {
        // 网络断开且未弹窗时,触发警告
        if (!connectionManager.isConnected && !_hasShownOfflineDialog) {
          _hasShownOfflineDialog = true;
          WidgetsBinding.instance.addPostFrameCallback((_) {
            _showOfflineWarning(context);
          });
        }
        // 网络恢复时重置弹窗标记
        if (connectionManager.isConnected && _hasShownOfflineDialog) {
          _hasShownOfflineDialog = false;
        }
        return MaterialApp.router(
          routerConfig: AppRoute().route,
          localizationsDelegates: AppLocalizations.localizationsDelegates,
          supportedLocales: AppLocalizations.supportedLocales,
          debugShowCheckedModeBanner: false,
        );
      },
    );
  }

  void _showOfflineWarning(BuildContext context) {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) => AlertDialog(
        title: const Text('网络断开'),
        content: const Text('Wi-Fi和移动网络均已关闭,请检查网络设置'),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.pop(context);
              _hasShownOfflineDialog = false;
            },
            child: const Text('知道了'),
          ),
        ],
      ),
    );
  }
}

3. 依赖配置

确保pubspec.yaml中添加对应依赖:

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.5
  connectivity_plus: ^4.0.1
  internet_connection_checker: ^1.0.0+1

关键说明

  • connectivity_plus负责检测设备连接类型,internet_connection_checker负责验证实际网络连通性,两者结合避免"假在线"情况
  • 在ConnectionManager的dispose方法中取消所有订阅,防止内存泄漏
  • 通过Consumer在根Widget全局监听网络状态,确保任何页面都能触发离线警告
  • 用_hasShownOfflineDialog标记避免重复弹窗,网络恢复后重置标记

内容的提问来源于stack exchange,提问作者Jena.T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:35:08