I have a Stateful Widget which obtains a bloc from its parent:
class Page extends StatefulWidget {
@override
State<StatefulWidget> createState() =>
_PageState();
}
class _PageState extends State<Page> {
final TextEditingController mnemonicController = TextEditingController();
final _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
final MnemonicLogicBloc mnemonicLogicBloc =
BlocProvider.of<MnemonicLogicBloc>(context);
mnemonicLogicBloc.outCheckMnemonic.listen((isCorrect){
if (!isCorrect) {
SnackBar copySnack = SnackBar(content: Text('Wrong Mnemonic!'));
_scaffoldKey.currentState.showSnackBar(copySnack);
}
});
return Scaffold(
key: _scaffoldKey,
body: Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
child: TextField(
controller: mnemonicController,
),
),
RaisedButton(
onPressed: () {
mnemonicLogicBloc.isMnemonicCorrect(mnemonicController.text);
},
child: Text('Check', style: TextStyle(color: Colors.white)),
)
],
),
));
}
}
What I want to do is to check, when user press the button, if the string inserted is correct. The method I call in the bloc is:
void isMnemonicCorrect(String typedMnemonic){
if(typedMnemonic == _lastGeneratedMnemonic)
_inCheckMnemonic.add(true);
else
_inCheckMnemonic.add(false);
}
_inCheckMnemonic is the Sink of my Subject (I'm using rxDart), while outCheckMnemonic is my Stream. The problem is that, even though the bloc's 'isCorrect' method is called once, the listen callback is called twice (The SnackBar is shown twice). Why does this happen?
EDIT: I navigate to Page() simply using Navigator.push:
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) {
return Page();
}));
I'm able to retrieve the bloc because, when my app start I initialized the bloc:
return runApp(BlocProvider<ApplicationBloc>(
bloc: ApplicationBloc(),
child: BlocProvider<MnemonicLogicBloc>(
bloc: MnemonicLogicBloc(),
child: BlocProvider<HomePageBloc>(
bloc: HomePageBloc(),
child: App(),
),
)
));
When you add a new Widget
in your Navigator
avoid creating that widget inside the builder, instead declare a variable outside and reuse that variable in your builder, like this:
final page = Page();
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => page ), );
With this change we avoid that our widget is recreated many times in an unexpected way.