19
votes

We need close one screen and open a second screen. And show snackbar on the second screen from first screen.

I tried to use Navigator.push, but this screen is already open and we have this error

Bad state: Stream has already been listened to.

4

4 Answers

14
votes

Instead of Snackbar i would suggest you to use Flushbar plugin for flutter it is easy to use and it'll take care of everything and u can customize it to a great extent . Snackbar needs a scaffold ancestor to work but Flushbar doesn't and it takes care of all the extra stuff itself and provides with ton of cool features.

Flushbar Plugin here

3
votes

I'm not sure I understand 100% the use case you have but by returning results from screens and passing arguments to new routes, you can work around basically any scenario.

Let's take an example. A is the original screen, then you push screen B. Now you see B, perform some action there, pop it, you get back to screen A and you want to display a snackbar.

When you pop, you can return a result and handle that result from the "parent" screen as described in the "Return data from a screen" cookbook.

When you receive a result, you can either show a snackbar notification, or alternatively (in case there is a third screen), you can pass that result to another screen as argument.

0
votes
showSubmitRequestSnackBar(BuildContext context) async {

  Flushbar(
    flushbarPosition: FlushbarPosition.BOTTOM,
    message: "Request Successfully Saved",
    icon: Icon(
      Icons.info_outline,
      size: 28.0,
      color: Colors.red,
    ),
    backgroundColor: Colors.red,
    duration: Duration(seconds: 5),
    leftBarIndicatorColor: Colors.red,

  )
    ..show(context).then((r)=> Navigator.push(
        context, MaterialPageRoute(builder: (context) => ListPage(""))));
}
0
votes

Screen A

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => BScreen(
      callbackFunction: (String resMessage){
        print(resMessage);
      },
    ),
  ),
);

Screen B

class BScreen extends StatefulWidget {
  final Function callbackFunction;

  BScreen({required this.callbackFunction});

  @override
  _BScreenState createState() => _BScreenState();
}


class _BScreenState extends State<BScreen> {
  // 
  _performTask(){
    // add your task here
    // ..........
    String msg = 'Task has been added';
    widget.callbackFunction(msg);
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            _performTask();
          },
          child: Text('Click Here'),
        ),
      ),
    );
  }
}

This solution worked for me. Happy to help others :) Thanks for asking this question.