Flutter使用Cubit检测网络时出现黑屏闪烁问题求助
解决Flutter中ConnectivityCubit弹窗前黑屏闪烁问题
在Flutter项目中使用ConnectivityCubit检测网络连接状态,无网络时弹出AlertDialog提示用户,但弹窗出现前屏幕会短暂黑屏闪烁,该如何避免?
原代码
main.dart
void main() { runApp(BlocProvider( create: (BuildContext context) => ConnectivityCubit()..checkConnectivity(), lazy: false, child: MaterialApp(home: MyApp()), )); } class MyApp extends StatelessWidget { MyApp({super.key}); bool _isDialogDisplayed = false; @override Widget build(BuildContext context) { return BlocConsumer<ConnectivityCubit, ConnectivityState>( listener: (context, state) { if (state == ConnectivityState.disconnected) { _isDialogDisplayed = true; showDialog( context: context, builder: (context) => const AlertDialog( title: Text('No Internet'), content: Text('Please check your internet connection.'), ), ); } if (state == ConnectivityState.connected && _isDialogDisplayed == true) { Navigator.of(context).pop(); _isDialogDisplayed = false; } }, builder: (context, state) { if (state == ConnectivityState.init) { return const CircularProgressIndicator(); } return MaterialApp( // <-- 问题根源 home: Scaffold( body: state == ConnectivityState.connected ? const Center( child: Text('Hello World'), ) : const Center(child: CircularProgressIndicator()), ), ); }, ); } }
cubit.dart
import 'dart:async'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; enum ConnectivityState { connected, disconnected, init } class ConnectivityCubit extends Cubit<ConnectivityState> { final Connectivity _connectivity = Connectivity(); StreamSubscription<ConnectivityResult>? _subscription; late Stream<ConnectivityResult> streamValue; ConnectivityCubit() : super(ConnectivityState.init) { streamValue = _connectivity.onConnectivityChanged; _subscription = _connectivity.onConnectivityChanged.listen((result) { if (result == ConnectivityResult.none) { emit(ConnectivityState.disconnected); } else { emit(ConnectivityState.connected); } }); } checkConnectivity() async { final result = await _connectivity.checkConnectivity(); if (result == ConnectivityResult.none) { emit(ConnectivityState.disconnected); } else { emit(ConnectivityState.connected); } } @override Future<void> close() { _subscription?.cancel(); return super.close(); } }
问题原因
- 重复创建MaterialApp:外层已经存在一个MaterialApp作为BlocProvider的子组件,而BlocConsumer的builder中又返回了新的MaterialApp。每次网络状态变化时,新的MaterialApp会重新初始化应用核心配置(主题、路由、本地化等),这个过程会引发短暂黑屏。
- StatelessWidget状态不可靠:MyApp是StatelessWidget,其中的
_isDialogDisplayed变量会在widget重建时被重置,可能导致弹窗逻辑混乱(比如重复弹窗、无法正确关闭)。
解决方案(修改后的代码)
main.dart
void main() { runApp(BlocProvider( create: (BuildContext context) => ConnectivityCubit()..checkConnectivity(), lazy: false, child: const MaterialApp(home: MyApp()), )); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { bool _isDialogDisplayed = false; @override Widget build(BuildContext context) { return BlocConsumer<ConnectivityCubit, ConnectivityState>( listener: (context, state) { // 避免重复弹窗 if (state == ConnectivityState.disconnected && !_isDialogDisplayed) { setState(() => _isDialogDisplayed = true); showDialog( context: context, barrierDismissible: false, // 可选:禁止点击空白关闭弹窗 builder: (context) => const AlertDialog( title: Text('无网络连接'), content: Text('请检查你的网络连接状态。'), ), ).then((_) { // 弹窗关闭时重置状态 setState(() => _isDialogDisplayed = false); }); } // 网络恢复时关闭弹窗 if (state == ConnectivityState.connected && _isDialogDisplayed) { if (Navigator.canPop(context)) { Navigator.of(context).pop(); } } }, builder: (context, state) { if (state == ConnectivityState.init) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } return Scaffold( body: state == ConnectivityState.connected ? const Center(child: Text('Hello World')) : const Center(child: CircularProgressIndicator()), ); }, ); } }
修改说明
- 将MyApp改为StatefulWidget,确保
_isDialogDisplayed状态在widget重建时不会丢失。 - 移除BlocConsumer内部的MaterialApp,只保留外层唯一的MaterialApp,避免重复初始化导致黑屏。
- 优化弹窗逻辑:添加状态判断防止重复弹窗,通过
then方法在弹窗关闭时重置状态,增加Navigator.canPop避免无弹窗时调用pop报错。
内容的提问来源于stack exchange,提问作者Master Techie
相关产品推荐
相关产品推荐

