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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:32:44