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

Dio ErrorInterceptor捕获SocketException全局提示连接异常方案

Dio全局SocketException异常提示实现方案

你之前在顶层放置BlocListener不生效,核心原因是拦截器内的异常事件没有正确投递到全局可用的Bloc实例:要么是投递事件时用错了BuildContext导致拿不到对应Bloc,要么是拦截器回调触发时机和BlocListener的挂载生命周期不匹配。
以下方案不需要在每个请求页面单独加监听,也不需要做持续常驻的全局监听挂载,事件仅在异常触发时才会流转到UI层,无额外性能开销:

具体实现步骤

  • 第一步:实现一个轻量的全局异常通知单例,作为Dio拦截器和UI层的解耦通信通道,使用广播流做事件分发:
class NetworkErrorNotifier {
  static final NetworkErrorNotifier _instance = NetworkErrorNotifier._internal();
  factory NetworkErrorNotifier() => _instance;
  NetworkErrorNotifier._internal();

  final StreamController<String> _errorController = StreamController.broadcast();
  Stream<String> get errorStream => _errorController.stream;

  void pushConnectionError() {
    _errorController.add("网络连接异常,请检查设备网络状态");
  }
}
  • 第二步:修改Dio自定义ErrorInterceptor的逻辑,命中SocketException判断时直接向通知流推送事件,全程不需要操作UI、不需要获取BuildContext:
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
  if (err.error is SocketException) {
    NetworkErrorNotifier().pushConnectionError();
  }
  super.onError(err, handler);
}
  • 第三步:在应用根Widget(即MaterialApp对应的State)中做单次流订阅,收到异常事件时直接触发提示展示,订阅随根Widget生命周期销毁,不存在内存泄漏:

如果你项目中已经接入了不依赖上下文的Toast类组件,可以直接在流监听回调中调用Toast展示提示,无需配置导航Key。如果用Flutter原生SnackBar做提示,配置全局导航Key即可拿到合法的上下文,不依赖具体发起请求的页面。

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  StreamSubscription? _errorSubscription;
  final GlobalKey<NavigatorState> _navKey = GlobalKey<NavigatorState>();

  @override
  void initState() {
    super.initState();
    // 仅订阅一次,有事件推送时才触发逻辑
    _errorSubscription = NetworkErrorNotifier().errorStream.listen((errorMsg) {
      // 此处替换为你项目实际的提示组件调用逻辑
      _navKey.currentContext?.read<ScaffoldMessengerState>().showSnackBar(
        SnackBar(content: Text(errorMsg), duration: const Duration(seconds: 2))
      );
    });
  }

  @override
  void dispose() {
    // 组件销毁时取消订阅,避免内存泄漏
    _errorSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: _navKey,
      // 其余主题、路由、首页配置保持原有逻辑即可
    );
  }
}

方案优势

  • 完全解耦网络层和UI层,拦截器逻辑不需要感知任何页面相关的上下文
  • 不需要在LoginPage或其他嵌套视图中单独添加监听,任意页面发起请求触发SocketException都能正常弹出提示
  • 不存在持续常驻的全局监听开销,仅当异常事件推送时才会执行UI展示逻辑,符合你的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:31:06