I am trying to create following widget, in which pressing a button the user should be redirected to MainGameScreen().
Widget quitGame(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: Stack(
children: <Widget>[
Container(
padding:
EdgeInsets.only(left: 20, top: 30, right: 20, bottom: 20),
margin: EdgeInsets.only(top: 45),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black,
offset: Offset(0, 10),
blurRadius: 10),
]),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
"QUIT GAME",
textScaleFactor: 1,
style: TextStyle(
fontSize: 40, fontWeight: FontWeight.w600),
),
SizedBox(
height: 15,
),
Text(
"Are you sure you want to leave the game?",
textScaleFactor: 1,
style: TextStyle(fontSize: 14),
textAlign: TextAlign.center,
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.bottomCenter,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Color(0xFFec4688),
),
onPressed: () {
Navigator.of(context).pop();
},
child: Text("NO",
textScaleFactor: 1,
style: TextStyle(fontSize: 20))),
),
Align(
alignment: Alignment.bottomCenter,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Color(0xFF1fd281),
),
onPressed: () {
roundTimer.cancel();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MainGameScreen(),
),
);
},
child: Text("YES",
textScaleFactor: 1,
style: TextStyle(fontSize: 20))),
),
],
),
],
),
),
],
),
);
});
}
But when I do this I get the following error:
════════ Exception caught by widgets library ═══════════════════════════════════
The following ProviderNotFoundException was thrown building Builder:
Error: Could not find the correct Provider<AuthBloc> above this MainGameScreen Widget
Unfortunately I don't have good understanding of provider, so I would be grateful if someone could explain what is going wrong and how I can fix it. Thanks
The MainGameScreen Widget
must be a descendant of Provider
Widget. But here, you used MaterialPageRoute
to push a new route to your app, so MainGameScreen
will be in a new seperated branch of the widget tree, it's only parent is the Material App Widget
. So there is two solutions for this:
1. Place the ProviderWidget above the MaterialApp Widget. Ex:
Provider<AuthBloc>(
create: (context) => AuthBloc(),
dispose: (context, bloc) => bloc.dispose(), // remove it if there is no dispose method in your BLoC
child: MaterialApp(),
),
2. A trick, which is very useful but really hard to test and manage: Add a `static` method which look like this :
class MainGameScreen extends StatefulWidget {
static Widget create(BuildContext context) {
return Provider<AuthBloc>(
create: (_) => AuthBloc(),
child: MainGameScreen(),
);
}
and when we use MaterialPageRoute
to push, use:
MaterialPageRoute(
builder: (context) => MainGameScreen.create(context),
),
And with this solution, we had a Provider above the MainGameScreen
;). And remember this is very hard to add widget test so think twice before using it.
Sorry for my previous stupid explanation!