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
相关产品推荐
相关产品推荐

