Flutter:基于多状态变量显示Overlay功能失效问题求助
Flutter Riverpod状态管理与页面切换异常
场景说明
我有一个名为TestMain的Flutter页面,使用白色背景的Scaffold,页面body需要根据三个布尔状态切换显示内容:
- isLocked、isPaused:由Riverpod Stream Provider触发更新,通过StateProvider实现全局访问
- isCheating:由AppLifecycle事件触发,同样通过StateProvider实现全局访问
Provider定义
final isCheatingProvider = StateProvider.autoDispose<bool>((ref) => false);
isPausedProvider和isLockedProvider的定义与上述代码完全一致
完整页面代码
class TestMain extends ConsumerStatefulWidget { const TestMain({super.key}); @override ConsumerState<TestMain> createState() => _TestMainScreenState(); } class _TestMainScreenState extends ConsumerState<TestMain> with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) async { super.didChangeAppLifecycleState(state); final isCheating = ref.watch(isCheatingProvider.notifier); switch (state) { case AppLifecycleState.resumed: case AppLifecycleState.inactive: await sendCheatingAttempt(ref); setState(() { isCheating.state = true; }); break; case AppLifecycleState.paused: await sendCheatingAttempt(ref); setState(() { isCheating.state = true; }); break; case AppLifecycleState.detached: await sendCheatingAttempt(ref); setState(() { isCheating.state = true; }); break; } } @override Widget build(BuildContext context) { final List<Item> items = ref.watch(itemsProvider); final AsyncValue<dynamic> wsTestListenerMessage = ref.watch(testListenerProvider); final isLocked = ref.watch(isLockedProvider.notifier); final isPaused = ref.watch(isPausedProvider.notifier); final isCheating = ref.watch(isCheatingProvider.notifier); wsTestListenerMessage.when( loading: () => {}, error: (err, stack) => print('Test State Error: $err'), data: (message) async { Future.delayed(const Duration(seconds: 0), () { if (message["lock"] == true) { isLocked.state = true; } if (message["unlock"] == true) { isLocked.state = false; } if (message["paused"] == true) { isPaused.state = true; } if (message["resumed"] == true) { isPaused.state = false; } }); }, ); return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: isPaused.state ? const ErrorOverlay(text: 'paused') : isLocked.state || isCheating.state ? const ErrorOverlay(text: 'cheating') : const TestView()), ); } }
ErrorOverlay为自定义组件,作用是居中显示红色大文本
问题点
- 整体功能始终无法正常工作
- 为避免在build方法中修改Provider触发报错,用
Future.delayed(const Duration(seconds: 0), () {})包裹状态更新逻辑,但未解决问题 - 在
didChangeAppLifecycleState中通过setState修改isCheating状态,但监听器中使用setState会导致重复调用,进而让Overlay重复显示
内容的提问来源于stack exchange,提问作者Jasper
相关产品推荐
相关产品推荐

