点击按钮延迟4秒更新Cubit状态,出现BlocProvider找不到TestCubit报错
问题与解决方案
我希望点击按钮后4秒更新Cubit的状态,但触发了以下错误:
BlocProvider.of() called with a context that does not contain a TestCubit. ======== 手势处理捕获到异常 =============================================================== 处理手势时抛出以下断言: BlocProvider.of() 被传入的context中不包含TestCubit。 从传入BlocProvider.of<TestCubit>()的context开始,未找到任何祖先组件。 这种情况可能是因为你使用的context来自BlocProvider上方的widget。 使用的context为: MyHomePage(state: _MyHomePageState#ea89e) 抛出异常时的调用栈: #0 BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:103:7) #1 _MyHomePageState.build.<anonymous closure> (package:flutter_cubit/main.dart:58:34) #2 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1072:21) #3 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:253:24) #4 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:627:11) #5 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:306:5) #6 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:239:7) #7 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:615:9) #8 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12) #9 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9) #10 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13) #11 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18) #12 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7) #13 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:460:19) #14 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:440:22) #15 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:337:11) #16 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:395:7) #17 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:357:5) #18 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:314:7) #19 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:295:7) #20 _invoke1 (dart:ui/hooks.dart:167:13) #21 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:341:7) #22 _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31) Handler: "onTap" Recognizer: TapGestureRecognizer#97fe2 debugOwner: GestureDetector state: possible won arena finalPosition: Offset(188.3, 443.5) finalLocalPosition: Offset(30.8, 20.5) button: 1 sent tap down
问题原因
当前代码中,BlocProvider和ElevatedButton是Column的同级子组件,按钮使用的context来自MyHomePage,而BlocProvider是MyHomePage的子节点,因此按钮的上下文无法找到TestCubit实例。此外,TestState的子类未正确实现props方法,运行时会抛出未实现错误。
修正后的代码
main.dart
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_cubit/bloc/test_cubit.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Cubit Bloc'), ), body: Center( // 将BlocProvider移到Column外层,让按钮处于其上下文范围内 child: BlocProvider( create: (_) => TestCubit(), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ BlocBuilder<TestCubit, TestState>( builder: (context, state) { if (state is Loading) { return const CircularProgressIndicator(); } else if (state is Loaded) { return const Text('Loaded'); } return const Text('Error'); }, ), ElevatedButton( onPressed: () { BlocProvider.of<TestCubit>(context).getData(); }, child: const Text('Click') ) ], ), ), ) ); } }
test_cubit.dart
import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; part 'test_state.dart'; class TestCubit extends Cubit<TestState> { TestCubit() : super(Loading()); Future<void> getData() async { try { emit(Loading()); await Future.delayed(const Duration(seconds: 4)); emit(Loaded()); } catch (e) { emit(ErrorException()); } } }
test_state.dart
part of 'test_cubit.dart'; abstract class TestState extends Equatable { const TestState(); } class Loading extends TestState { const Loading(); @override List<Object?> get props => []; } class Loaded extends TestState { const Loaded(); @override List<Object?> get props => []; } class ErrorException extends TestState { const ErrorException(); @override List<Object?> get props => []; }
关键修改点
- 将
BlocProvider移动到Column的外层,确保按钮和BlocBuilder都处于BlocProvider的上下文范围内,这样按钮就能通过context获取到TestCubit实例。 - 实现
TestState子类的props方法,返回空列表(因为这些状态没有需要比较的属性),避免运行时抛出未实现错误。
内容的提问来源于stack exchange,提问作者user20393696
相关产品推荐
相关产品推荐

