'how to access flutter bloc in the initState method?
In the code shown below , the dispatch event is called from within the build method after getting the BuildContext object. What if I wish to do is to dispatch an event during processing at the start of the page within the initState method itself ?
If I use didChangeDependencies method , then I am getting this error :
BlocProvider.of() called with a context that does not contain a Bloc of type FileManagerBloc.
how to fix this?
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider<FileManagerBloc>(
builder: (context)=>FileManagerBloc(),
child: SafeArea(
child: Container(
child: Column(
children: <Widget>[
Container(color: Colors.blueGrey, child: TopMenuBar()),
Expanded(
child: BlocBuilder<FileManagerBloc,FileManagerState>(
builder: (context , state){
return GridView.count(
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
crossAxisCount: 3,
crossAxisSpacing: 10,
children: getFilesListWidget(context , state),
);
},
),
)
],
),
),
),
));
}
@override
void dispose() {
super.dispose();
}
@override
void didChangeDependencies() {
logger.i('Did change dependency Called');
final FileManagerBloc bloc = BlocProvider.of<FileManagerBloc>(context) ;
Messenger.sendGetHomeDir()
.then((path) async {
final files = await Messenger.sendListDir(path);
bloc.dispatch(SetCurrentWorkingDir(path)) ;
bloc.dispatch(UpdateFileSystemCacheMapping(path , files)) ;
});
}
Solution 1:[1]
The problem is that you are initializing the instance of FileManagerBloc
inside the BlocProvider
which is, of course inaccessible to the parent widget. I know that helps with automatic cleanup of the Bloc
but if you want to access it inside initState
or didChangeDependencies
then you have to initialize it at the parent level like so,
FileManagerBloc _fileManagerBloc;
@override
void initState() {
super.initState();
_fileManagerBloc= FileManagerBloc();
_fileManagerBloc.dispatch(LoadEducation());
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider<FileManagerBloc>(
builder: (context)=> _fileManagerBloc,
child: SafeArea(
child: Container(
child: Column(
children: <Widget>[
Container(color: Colors.blueGrey, child: TopMenuBar()),
Expanded(
child: BlocBuilder<FileManagerBloc,FileManagerState>(
builder: (context , state){
return GridView.count(
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
crossAxisCount: 3,
crossAxisSpacing: 10,
children: getFilesListWidget(context , state),
);
},
),
)
],
),
),
),
));
}
@override
void dispose() {
_fileManagerBloc.dispose();
super.dispose();
}
@override
void didChangeDependencies() {
logger.i('Did change dependency Called');
Messenger.sendGetHomeDir()
.then((path) async {
final files = await Messenger.sendListDir(path);
_fileManagerBloc.dispatch(SetCurrentWorkingDir(path)) ;
_fileManagerBloc.dispatch(UpdateFileSystemCacheMapping(path , files)) ;
});
}
alternatively, if FileManagerBloc
was provided/initialized at a grandparent Widget
then it could easily be accessible at this
level through BlocProvider.of<CounterBloc>(context);
Solution 2:[2]
you can use it in didChangeDependencies
method rather than initState
.
Example
@override
void didChangeDependencies() {
final CounterBloc counterBloc = BlocProvider.of<CounterBloc>(context);
//do whatever you want with the bloc here.
super.didChangeDependencies();
}
Solution 3:[3]
Solution: Step 1: need apply singleton pattern on Bloc class
class AuthBloc extends Bloc<AuthEvent, AuthState> {
static AuthBloc? _instance;
static AuthBloc get instance {
if (_instance == null) _instance = AuthBloc();
return _instance!;
}
....
....
Step 2: use AuthBloc.instance on main.dart for Provider
void main() async {
runApp(MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => AuthBloc.instance,
),
...
...
],
child: App(),
));
}
Now you can use Bloc without context
- you can get state by AuthBloc.instance.state from initState or anywhere
- you can add event from anywhere by AuthBloc.instance.add(..)
- you also call BlocA from another BlocB very simple
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Oliver Atienza |
Solution 2 | Karim Elghamry |
Solution 3 | nghe.huavan |