I want to change the state of cubit after 4 seconds when i click the button but it gives error :
**BlocProvider.of() called with a context that does not contain a TestCubit.
======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
BlocProvider.of() called with a context that does not contain a TestCubit.
No ancestor could be found starting from the context that was passed to BlocProvider.of<TestCubit>().
This can happen if the context you used comes from a widget above the BlocProvider.
The context used was: MyHomePage(state: _MyHomePageState#ea89e)
When the exception was thrown, this was the stack:
#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**
My code here:
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: Text('Cubit Bloc'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BlocProvider(
create: (_) => TestCubit(),
child: BlocBuilder<TestCubit, TestState>(
builder: (context, state) {
if (state is Loading) {
return CircularProgressIndicator();
} else
if (state is Loaded) {
return Text('Loaded');
}
return Text('Error');
},
),
),
ElevatedButton(
onPressed: () {
BlocProvider.of<TestCubit>(context).getData();
},
child: Text('Click')
)
],
)
)
);
}
}
test_cubit
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(Duration(seconds: 4));
emit(Loaded());
} catch (e) {
emit(ErrorException());
}
}
}
test_state
part of 'test_cubit.dart';
abstract class TestState extends Equatable {
const TestState();
}
class Loading extends TestState {
const Loading();
@override
// TODO: implement props
List<Object?> get props => throw UnimplementedError();
}
class Loaded extends TestState {
const Loaded();
@override
// TODO: implement props
List<Object?> get props => throw UnimplementedError();
}
class ErrorException extends TestState {
const ErrorException();
@override
// TODO: implement props
List<Object?> get props => throw UnimplementedError();
}
CodePudding user response:
You have two ways to do this.
Firstly please keep remind that BlocProvider.of
only finds that bloc object which is top of widget tree. You are putting TestBloc()
in the peer widget. The widget you attach TestBloc()
should cover the place which you are using BlocProvider.of
**IMPORTANT: ** But I prefer the other way as it is pretty easy to understand
Declare var testBloc=TestBloc();
outside of build method inside the widgetState class. Then instead of BlocProvider.of
use testBloc.someMethod
. Don’t forget to put it here too:
BlocProvider(
create: (_) => testCubit,
CodePudding user response:
you are using BlocProvider in the wrong scope, try moving BlocProvider outside of MyHomePage class
try this:
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 BlocProvider(
create: (context) => TestCubit(),
child: 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: Text('Cubit Bloc'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BlocBuilder<TestCubit, TestState>(
builder: (context, state) {
if (state is Loading) {
return CircularProgressIndicator();
} else if (state is Loaded) {
return Text('Loaded');
}
return Text('Error');
},
),
ElevatedButton(
onPressed: () {
BlocProvider.of<TestCubit>(context).getData();
},
child: Text('Click')
)
],
)
)
);
}
}