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

Flutter中如何在Stream Builder内实现独立导航?

解决方案

核心思路是让网络状态监听的StreamBuilder包裹整个应用的导航结构,而非仅作为初始页面的父组件。这样所有页面(包括通过push或showModalBottomSheet打开的页面)都会处于StreamBuilder的监听范围内,网络状态变化时能实时触发UI更新。

具体实现方式

1. 将StreamBuilder作为应用根组件

直接用监听网络状态的StreamBuilder包裹MaterialApp,让整个导航栈都处于StreamBuilder的子树中:

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

class MyApp extends StatelessWidget {
  // 网络状态流
  final Stream<ConnectivityResult> _connectivityStream = Connectivity().onConnectivityChanged;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<ConnectivityResult>(
      stream: _connectivityStream,
      initialData: ConnectivityResult.none, // 初始状态设为无网络
      builder: (context, snapshot) {
        final hasNetwork = snapshot.data != ConnectivityResult.none;

        // 整个MaterialApp都在StreamBuilder内部,所有导航操作均在此范围内
        return MaterialApp(
          title: 'Network Demo',
          theme: ThemeData(primarySwatch: Colors.blue),
          // 根据网络状态设置初始页面
          home: hasNetwork ? AuthGate() : NoNetworkPage(),
          // 其他路由配置(如果有)
          routes: {
            '/details': (context) => DetailsPage(),
          },
        );
      },
    );
  }
}

// 无网络页面示例
class NoNetworkPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('无网络连接,请检查网络设置')),
    );
  }
}

// AuthGate示例(内部可包含自己的StreamBuilder)
class AuthGate extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      // 你的认证流逻辑
      stream: /* 认证状态流 */,
      builder: (context, snapshot) {
        return TabBarView(
          children: [/* 你的Tab页面 */],
        );
      },
    );
  }
}

2. 处理网络状态切换时的导航栈

如果需要在网络断开时强制跳转到无网络页面,恢复后回到之前的页面,可以在StreamBuilder中添加导航逻辑:

builder: (context, snapshot) {
  final hasNetwork = snapshot.data != ConnectivityResult.none;
  final navigatorKey = GlobalKey<NavigatorState>();

  WidgetsBinding.instance.addPostFrameCallback((_) {
    final currentContext = navigatorKey.currentContext;
    if (currentContext == null) return;

    if (!hasNetwork) {
      // 清空栈并跳转到无网络页面
      Navigator.of(currentContext).pushAndRemoveUntil(
        MaterialPageRoute(builder: (_) => NoNetworkPage()),
        (route) => false,
      );
    } else {
      // 如果当前在无网络页面,回到AuthGate
      final currentRoute = ModalRoute.of(currentContext)?.settings.name;
      if (currentRoute == '/no-network') {
        Navigator.of(currentContext).pushAndRemoveUntil(
          MaterialPageRoute(builder: (_) => AuthGate()),
          (route) => false,
        );
      }
    }
  });

  return MaterialApp(
    navigatorKey: navigatorKey,
    home: hasNetwork ? AuthGate() : NoNetworkPage(),
  );
}

3. 页面内独立监听网络状态(可选)

如果需要在单个页面内单独处理网络变化,可以直接复用同一个网络流,无需依赖上层StreamBuilder:

class DetailsPage extends StatelessWidget {
  final Stream<ConnectivityResult> _connectivityStream = Connectivity().onConnectivityChanged;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<ConnectivityResult>(
      stream: _connectivityStream,
      builder: (context, snapshot) {
        final hasNetwork = snapshot.data != ConnectivityResult.none;
        return Scaffold(
          appBar: AppBar(title: Text('详情页')),
          body: hasNetwork 
              ? Text('当前有网络') 
              : Text('当前无网络,无法加载内容'),
        );
      },
    );
  }
}

方案优势

  • 整个应用的导航结构都处于网络监听范围内,无论跳转至哪个页面,都能实时响应网络状态变化。
  • 无需修改AuthGate内部逻辑,避免繁琐的变量传递与状态同步,保持代码结构清晰。
  • 完全基于Flutter原生组件实现,无需引入额外状态管理库。

内容的提问来源于stack exchange,提问作者Globe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:40:19