flutter snackbar display based on stream












2















I currently have an interesting issue related to displaying of a snackbar based on a user action.



Above sounds very trivial, but lets elaborate:



I have 2 screens:




  1. list of employees

  2. Add employee


The application uses the bloc pattern (with streams/rxdart).



Here is what I want:




  • User clicks on add employee FAB button in list of employees screen and is navigated to the Add Employee screen (works perfectly fine)

  • User fills in employee details and clicks save

  • Upon save, employee is added to the stream, and updated the list of employees screen (works fine)

  • User is navigated BACK to list of employees (works fine)

  • Snackbar is displayed stating that the employee has successfully been added (This is the problem)


I tried several ways of implementing this:



Add a new stream (employeeAdded), and when adding an employee to the employees stream, additionally push a boolean to employee added.



In the list of employees, add a new stream builder and in the builder logic add the snackbar.



This gives all sorts of problems, for example trying to display the snackbar before the page has been (re)build, and so on.



The question is twofold: What is good UX practice for this scenario, and what would be a good solution for this problem?



(will post code on request)



Thanks for the help!










share|improve this question



























    2















    I currently have an interesting issue related to displaying of a snackbar based on a user action.



    Above sounds very trivial, but lets elaborate:



    I have 2 screens:




    1. list of employees

    2. Add employee


    The application uses the bloc pattern (with streams/rxdart).



    Here is what I want:




    • User clicks on add employee FAB button in list of employees screen and is navigated to the Add Employee screen (works perfectly fine)

    • User fills in employee details and clicks save

    • Upon save, employee is added to the stream, and updated the list of employees screen (works fine)

    • User is navigated BACK to list of employees (works fine)

    • Snackbar is displayed stating that the employee has successfully been added (This is the problem)


    I tried several ways of implementing this:



    Add a new stream (employeeAdded), and when adding an employee to the employees stream, additionally push a boolean to employee added.



    In the list of employees, add a new stream builder and in the builder logic add the snackbar.



    This gives all sorts of problems, for example trying to display the snackbar before the page has been (re)build, and so on.



    The question is twofold: What is good UX practice for this scenario, and what would be a good solution for this problem?



    (will post code on request)



    Thanks for the help!










    share|improve this question

























      2












      2








      2








      I currently have an interesting issue related to displaying of a snackbar based on a user action.



      Above sounds very trivial, but lets elaborate:



      I have 2 screens:




      1. list of employees

      2. Add employee


      The application uses the bloc pattern (with streams/rxdart).



      Here is what I want:




      • User clicks on add employee FAB button in list of employees screen and is navigated to the Add Employee screen (works perfectly fine)

      • User fills in employee details and clicks save

      • Upon save, employee is added to the stream, and updated the list of employees screen (works fine)

      • User is navigated BACK to list of employees (works fine)

      • Snackbar is displayed stating that the employee has successfully been added (This is the problem)


      I tried several ways of implementing this:



      Add a new stream (employeeAdded), and when adding an employee to the employees stream, additionally push a boolean to employee added.



      In the list of employees, add a new stream builder and in the builder logic add the snackbar.



      This gives all sorts of problems, for example trying to display the snackbar before the page has been (re)build, and so on.



      The question is twofold: What is good UX practice for this scenario, and what would be a good solution for this problem?



      (will post code on request)



      Thanks for the help!










      share|improve this question














      I currently have an interesting issue related to displaying of a snackbar based on a user action.



      Above sounds very trivial, but lets elaborate:



      I have 2 screens:




      1. list of employees

      2. Add employee


      The application uses the bloc pattern (with streams/rxdart).



      Here is what I want:




      • User clicks on add employee FAB button in list of employees screen and is navigated to the Add Employee screen (works perfectly fine)

      • User fills in employee details and clicks save

      • Upon save, employee is added to the stream, and updated the list of employees screen (works fine)

      • User is navigated BACK to list of employees (works fine)

      • Snackbar is displayed stating that the employee has successfully been added (This is the problem)


      I tried several ways of implementing this:



      Add a new stream (employeeAdded), and when adding an employee to the employees stream, additionally push a boolean to employee added.



      In the list of employees, add a new stream builder and in the builder logic add the snackbar.



      This gives all sorts of problems, for example trying to display the snackbar before the page has been (re)build, and so on.



      The question is twofold: What is good UX practice for this scenario, and what would be a good solution for this problem?



      (will post code on request)



      Thanks for the help!







      flutter rxdart






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 3 at 13:25









      Joey RoosingJoey Roosing

      1,43231936




      1,43231936
























          3 Answers
          3






          active

          oldest

          votes


















          1














          @joey I have found a solution but I'm not sure that it's the best. I'm changing my app to bloc pattern now so I found the same problem as you so I did this:



          On my bloc file y put a controller only for the scaffoldState:



          ScaffoldState scaffold;



          StreamController<ScaffoldState> _scaffoldController = StreamController<ScaffoldState>();
          StreamSink<ScaffoldState> get setScaffold => _scaffoldController.sink;



          And on the constructor of the bloc file y listen for that stream:



          LoginBloc(){
          _scaffoldController.stream.listen((sc){ scaffold = sc;});
          }



          On the widget I sink the scaffoldState whenever I want to use it:



          onPressed:() {
          bloc.setScaffold.add(Scaffold.of(context));
          }



          so then, I can show snackbars as usuall from the bloc:



          scaffold.showSnackBar(SnackBar(content: Text(hi world'),),);






          share|improve this answer



















          • 2





            Oh, an interesting approach. The only problem I have with this is you are kind of mixing UI logic with your bloc. If you want to reuse your business logic in for example an angular app, this bloc will give errors because ScaffoldState doesn't exist. I do like the idea though, thanks for the insight!

            – Joey Roosing
            Jan 9 at 11:06





















          0














          Although its not my favourite answer, I am also not sure if there is a better alternative; this is what I did as a temporary fix for future watchers:



          Create a new stream (in my case employeeAdded), upon adding employees, also create an entry into the stream:



            final _employees = BehaviorSubject<List<Employee>>(seedValue: List<Employee>());
          final _employeeAdded = BehaviorSubject();

          // streams (out)
          Observable<List<Employee>> get employees => _employees.stream;
          Observable<dynamic> get employeesAdded => _employeeAdded.stream;

          addEmployee(Employee employee) async {
          final newList = <Employee>..addAll(_employees.value)..add(employee);
          await _employeeRepo.upsertEmployee(employee);
          _employees.add(newList);

          _employeeAdded.add(true);
          //FIXME: Save to db
          }


          Note there is no seedValue in employeeAdded, this is to prevent the snackbar from showing on initial load.



          In my screen / page I have a scaffold; it's body calls another method which should explain the rest of the code:



           Widget _buildBody(EmployeeBloc bloc) {
          return StreamBuilder(
          stream: bloc.employees,
          builder: (context, snapshot) {
          if (!snapshot.hasData) {
          bloc.employeesAdded.listen(
          (_) => Scaffold.of(context).showSnackBar(
          SnackBar(
          content: Text('Employee added'),
          ),
          ),
          );
          bloc.seedEmployees();
          return Center(
          child: Text("No employees"),
          );
          }
          return _buildList(bloc, snapshot.data);
          },
          );
          }


          Note the listen on the bloc with the hasData if.



          This works for now, but would like to know if there is a more neat example.






          share|improve this answer
























          • can cause issues (memory leak?) because everytime !hasData passes, a new listener is added

            – Joey Roosing
            Jan 7 at 10:56



















          0














          Wrap your body (the child of your Scaffold, in your case returned by _buildBody) with a Builder so you get to write some "free" code with the context.



          Now you can listen to the stream with a handler you provide (like you already did), but this time you register the listener only once per Scaffold build (and not registering a listener at each event occurred in employeesAdded stream).



            @override
          Widget build(BuildContext context) {
          return Scaffold(
          body: Builder(
          builder: (BuildContext context) {
          bloc.employeesAdded.listen(
          (_) {
          Scaffold.of(context).showSnackBar(
          SnackBar(
          content: Text('Employee added'),
          ), // SnackBar
          );
          },
          );

          return _buildBody(bloc);
          },
          ), // Builder
          ); // Scaffold
          }





          share|improve this answer
























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54023203%2fflutter-snackbar-display-based-on-stream%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            @joey I have found a solution but I'm not sure that it's the best. I'm changing my app to bloc pattern now so I found the same problem as you so I did this:



            On my bloc file y put a controller only for the scaffoldState:



            ScaffoldState scaffold;



            StreamController<ScaffoldState> _scaffoldController = StreamController<ScaffoldState>();
            StreamSink<ScaffoldState> get setScaffold => _scaffoldController.sink;



            And on the constructor of the bloc file y listen for that stream:



            LoginBloc(){
            _scaffoldController.stream.listen((sc){ scaffold = sc;});
            }



            On the widget I sink the scaffoldState whenever I want to use it:



            onPressed:() {
            bloc.setScaffold.add(Scaffold.of(context));
            }



            so then, I can show snackbars as usuall from the bloc:



            scaffold.showSnackBar(SnackBar(content: Text(hi world'),),);






            share|improve this answer



















            • 2





              Oh, an interesting approach. The only problem I have with this is you are kind of mixing UI logic with your bloc. If you want to reuse your business logic in for example an angular app, this bloc will give errors because ScaffoldState doesn't exist. I do like the idea though, thanks for the insight!

              – Joey Roosing
              Jan 9 at 11:06


















            1














            @joey I have found a solution but I'm not sure that it's the best. I'm changing my app to bloc pattern now so I found the same problem as you so I did this:



            On my bloc file y put a controller only for the scaffoldState:



            ScaffoldState scaffold;



            StreamController<ScaffoldState> _scaffoldController = StreamController<ScaffoldState>();
            StreamSink<ScaffoldState> get setScaffold => _scaffoldController.sink;



            And on the constructor of the bloc file y listen for that stream:



            LoginBloc(){
            _scaffoldController.stream.listen((sc){ scaffold = sc;});
            }



            On the widget I sink the scaffoldState whenever I want to use it:



            onPressed:() {
            bloc.setScaffold.add(Scaffold.of(context));
            }



            so then, I can show snackbars as usuall from the bloc:



            scaffold.showSnackBar(SnackBar(content: Text(hi world'),),);






            share|improve this answer



















            • 2





              Oh, an interesting approach. The only problem I have with this is you are kind of mixing UI logic with your bloc. If you want to reuse your business logic in for example an angular app, this bloc will give errors because ScaffoldState doesn't exist. I do like the idea though, thanks for the insight!

              – Joey Roosing
              Jan 9 at 11:06
















            1












            1








            1







            @joey I have found a solution but I'm not sure that it's the best. I'm changing my app to bloc pattern now so I found the same problem as you so I did this:



            On my bloc file y put a controller only for the scaffoldState:



            ScaffoldState scaffold;



            StreamController<ScaffoldState> _scaffoldController = StreamController<ScaffoldState>();
            StreamSink<ScaffoldState> get setScaffold => _scaffoldController.sink;



            And on the constructor of the bloc file y listen for that stream:



            LoginBloc(){
            _scaffoldController.stream.listen((sc){ scaffold = sc;});
            }



            On the widget I sink the scaffoldState whenever I want to use it:



            onPressed:() {
            bloc.setScaffold.add(Scaffold.of(context));
            }



            so then, I can show snackbars as usuall from the bloc:



            scaffold.showSnackBar(SnackBar(content: Text(hi world'),),);






            share|improve this answer













            @joey I have found a solution but I'm not sure that it's the best. I'm changing my app to bloc pattern now so I found the same problem as you so I did this:



            On my bloc file y put a controller only for the scaffoldState:



            ScaffoldState scaffold;



            StreamController<ScaffoldState> _scaffoldController = StreamController<ScaffoldState>();
            StreamSink<ScaffoldState> get setScaffold => _scaffoldController.sink;



            And on the constructor of the bloc file y listen for that stream:



            LoginBloc(){
            _scaffoldController.stream.listen((sc){ scaffold = sc;});
            }



            On the widget I sink the scaffoldState whenever I want to use it:



            onPressed:() {
            bloc.setScaffold.add(Scaffold.of(context));
            }



            so then, I can show snackbars as usuall from the bloc:



            scaffold.showSnackBar(SnackBar(content: Text(hi world'),),);







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 9 at 9:26









            Jose JetJose Jet

            916




            916








            • 2





              Oh, an interesting approach. The only problem I have with this is you are kind of mixing UI logic with your bloc. If you want to reuse your business logic in for example an angular app, this bloc will give errors because ScaffoldState doesn't exist. I do like the idea though, thanks for the insight!

              – Joey Roosing
              Jan 9 at 11:06
















            • 2





              Oh, an interesting approach. The only problem I have with this is you are kind of mixing UI logic with your bloc. If you want to reuse your business logic in for example an angular app, this bloc will give errors because ScaffoldState doesn't exist. I do like the idea though, thanks for the insight!

              – Joey Roosing
              Jan 9 at 11:06










            2




            2





            Oh, an interesting approach. The only problem I have with this is you are kind of mixing UI logic with your bloc. If you want to reuse your business logic in for example an angular app, this bloc will give errors because ScaffoldState doesn't exist. I do like the idea though, thanks for the insight!

            – Joey Roosing
            Jan 9 at 11:06







            Oh, an interesting approach. The only problem I have with this is you are kind of mixing UI logic with your bloc. If you want to reuse your business logic in for example an angular app, this bloc will give errors because ScaffoldState doesn't exist. I do like the idea though, thanks for the insight!

            – Joey Roosing
            Jan 9 at 11:06















            0














            Although its not my favourite answer, I am also not sure if there is a better alternative; this is what I did as a temporary fix for future watchers:



            Create a new stream (in my case employeeAdded), upon adding employees, also create an entry into the stream:



              final _employees = BehaviorSubject<List<Employee>>(seedValue: List<Employee>());
            final _employeeAdded = BehaviorSubject();

            // streams (out)
            Observable<List<Employee>> get employees => _employees.stream;
            Observable<dynamic> get employeesAdded => _employeeAdded.stream;

            addEmployee(Employee employee) async {
            final newList = <Employee>..addAll(_employees.value)..add(employee);
            await _employeeRepo.upsertEmployee(employee);
            _employees.add(newList);

            _employeeAdded.add(true);
            //FIXME: Save to db
            }


            Note there is no seedValue in employeeAdded, this is to prevent the snackbar from showing on initial load.



            In my screen / page I have a scaffold; it's body calls another method which should explain the rest of the code:



             Widget _buildBody(EmployeeBloc bloc) {
            return StreamBuilder(
            stream: bloc.employees,
            builder: (context, snapshot) {
            if (!snapshot.hasData) {
            bloc.employeesAdded.listen(
            (_) => Scaffold.of(context).showSnackBar(
            SnackBar(
            content: Text('Employee added'),
            ),
            ),
            );
            bloc.seedEmployees();
            return Center(
            child: Text("No employees"),
            );
            }
            return _buildList(bloc, snapshot.data);
            },
            );
            }


            Note the listen on the bloc with the hasData if.



            This works for now, but would like to know if there is a more neat example.






            share|improve this answer
























            • can cause issues (memory leak?) because everytime !hasData passes, a new listener is added

              – Joey Roosing
              Jan 7 at 10:56
















            0














            Although its not my favourite answer, I am also not sure if there is a better alternative; this is what I did as a temporary fix for future watchers:



            Create a new stream (in my case employeeAdded), upon adding employees, also create an entry into the stream:



              final _employees = BehaviorSubject<List<Employee>>(seedValue: List<Employee>());
            final _employeeAdded = BehaviorSubject();

            // streams (out)
            Observable<List<Employee>> get employees => _employees.stream;
            Observable<dynamic> get employeesAdded => _employeeAdded.stream;

            addEmployee(Employee employee) async {
            final newList = <Employee>..addAll(_employees.value)..add(employee);
            await _employeeRepo.upsertEmployee(employee);
            _employees.add(newList);

            _employeeAdded.add(true);
            //FIXME: Save to db
            }


            Note there is no seedValue in employeeAdded, this is to prevent the snackbar from showing on initial load.



            In my screen / page I have a scaffold; it's body calls another method which should explain the rest of the code:



             Widget _buildBody(EmployeeBloc bloc) {
            return StreamBuilder(
            stream: bloc.employees,
            builder: (context, snapshot) {
            if (!snapshot.hasData) {
            bloc.employeesAdded.listen(
            (_) => Scaffold.of(context).showSnackBar(
            SnackBar(
            content: Text('Employee added'),
            ),
            ),
            );
            bloc.seedEmployees();
            return Center(
            child: Text("No employees"),
            );
            }
            return _buildList(bloc, snapshot.data);
            },
            );
            }


            Note the listen on the bloc with the hasData if.



            This works for now, but would like to know if there is a more neat example.






            share|improve this answer
























            • can cause issues (memory leak?) because everytime !hasData passes, a new listener is added

              – Joey Roosing
              Jan 7 at 10:56














            0












            0








            0







            Although its not my favourite answer, I am also not sure if there is a better alternative; this is what I did as a temporary fix for future watchers:



            Create a new stream (in my case employeeAdded), upon adding employees, also create an entry into the stream:



              final _employees = BehaviorSubject<List<Employee>>(seedValue: List<Employee>());
            final _employeeAdded = BehaviorSubject();

            // streams (out)
            Observable<List<Employee>> get employees => _employees.stream;
            Observable<dynamic> get employeesAdded => _employeeAdded.stream;

            addEmployee(Employee employee) async {
            final newList = <Employee>..addAll(_employees.value)..add(employee);
            await _employeeRepo.upsertEmployee(employee);
            _employees.add(newList);

            _employeeAdded.add(true);
            //FIXME: Save to db
            }


            Note there is no seedValue in employeeAdded, this is to prevent the snackbar from showing on initial load.



            In my screen / page I have a scaffold; it's body calls another method which should explain the rest of the code:



             Widget _buildBody(EmployeeBloc bloc) {
            return StreamBuilder(
            stream: bloc.employees,
            builder: (context, snapshot) {
            if (!snapshot.hasData) {
            bloc.employeesAdded.listen(
            (_) => Scaffold.of(context).showSnackBar(
            SnackBar(
            content: Text('Employee added'),
            ),
            ),
            );
            bloc.seedEmployees();
            return Center(
            child: Text("No employees"),
            );
            }
            return _buildList(bloc, snapshot.data);
            },
            );
            }


            Note the listen on the bloc with the hasData if.



            This works for now, but would like to know if there is a more neat example.






            share|improve this answer













            Although its not my favourite answer, I am also not sure if there is a better alternative; this is what I did as a temporary fix for future watchers:



            Create a new stream (in my case employeeAdded), upon adding employees, also create an entry into the stream:



              final _employees = BehaviorSubject<List<Employee>>(seedValue: List<Employee>());
            final _employeeAdded = BehaviorSubject();

            // streams (out)
            Observable<List<Employee>> get employees => _employees.stream;
            Observable<dynamic> get employeesAdded => _employeeAdded.stream;

            addEmployee(Employee employee) async {
            final newList = <Employee>..addAll(_employees.value)..add(employee);
            await _employeeRepo.upsertEmployee(employee);
            _employees.add(newList);

            _employeeAdded.add(true);
            //FIXME: Save to db
            }


            Note there is no seedValue in employeeAdded, this is to prevent the snackbar from showing on initial load.



            In my screen / page I have a scaffold; it's body calls another method which should explain the rest of the code:



             Widget _buildBody(EmployeeBloc bloc) {
            return StreamBuilder(
            stream: bloc.employees,
            builder: (context, snapshot) {
            if (!snapshot.hasData) {
            bloc.employeesAdded.listen(
            (_) => Scaffold.of(context).showSnackBar(
            SnackBar(
            content: Text('Employee added'),
            ),
            ),
            );
            bloc.seedEmployees();
            return Center(
            child: Text("No employees"),
            );
            }
            return _buildList(bloc, snapshot.data);
            },
            );
            }


            Note the listen on the bloc with the hasData if.



            This works for now, but would like to know if there is a more neat example.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 3 at 15:35









            Joey RoosingJoey Roosing

            1,43231936




            1,43231936













            • can cause issues (memory leak?) because everytime !hasData passes, a new listener is added

              – Joey Roosing
              Jan 7 at 10:56



















            • can cause issues (memory leak?) because everytime !hasData passes, a new listener is added

              – Joey Roosing
              Jan 7 at 10:56

















            can cause issues (memory leak?) because everytime !hasData passes, a new listener is added

            – Joey Roosing
            Jan 7 at 10:56





            can cause issues (memory leak?) because everytime !hasData passes, a new listener is added

            – Joey Roosing
            Jan 7 at 10:56











            0














            Wrap your body (the child of your Scaffold, in your case returned by _buildBody) with a Builder so you get to write some "free" code with the context.



            Now you can listen to the stream with a handler you provide (like you already did), but this time you register the listener only once per Scaffold build (and not registering a listener at each event occurred in employeesAdded stream).



              @override
            Widget build(BuildContext context) {
            return Scaffold(
            body: Builder(
            builder: (BuildContext context) {
            bloc.employeesAdded.listen(
            (_) {
            Scaffold.of(context).showSnackBar(
            SnackBar(
            content: Text('Employee added'),
            ), // SnackBar
            );
            },
            );

            return _buildBody(bloc);
            },
            ), // Builder
            ); // Scaffold
            }





            share|improve this answer




























              0














              Wrap your body (the child of your Scaffold, in your case returned by _buildBody) with a Builder so you get to write some "free" code with the context.



              Now you can listen to the stream with a handler you provide (like you already did), but this time you register the listener only once per Scaffold build (and not registering a listener at each event occurred in employeesAdded stream).



                @override
              Widget build(BuildContext context) {
              return Scaffold(
              body: Builder(
              builder: (BuildContext context) {
              bloc.employeesAdded.listen(
              (_) {
              Scaffold.of(context).showSnackBar(
              SnackBar(
              content: Text('Employee added'),
              ), // SnackBar
              );
              },
              );

              return _buildBody(bloc);
              },
              ), // Builder
              ); // Scaffold
              }





              share|improve this answer


























                0












                0








                0







                Wrap your body (the child of your Scaffold, in your case returned by _buildBody) with a Builder so you get to write some "free" code with the context.



                Now you can listen to the stream with a handler you provide (like you already did), but this time you register the listener only once per Scaffold build (and not registering a listener at each event occurred in employeesAdded stream).



                  @override
                Widget build(BuildContext context) {
                return Scaffold(
                body: Builder(
                builder: (BuildContext context) {
                bloc.employeesAdded.listen(
                (_) {
                Scaffold.of(context).showSnackBar(
                SnackBar(
                content: Text('Employee added'),
                ), // SnackBar
                );
                },
                );

                return _buildBody(bloc);
                },
                ), // Builder
                ); // Scaffold
                }





                share|improve this answer













                Wrap your body (the child of your Scaffold, in your case returned by _buildBody) with a Builder so you get to write some "free" code with the context.



                Now you can listen to the stream with a handler you provide (like you already did), but this time you register the listener only once per Scaffold build (and not registering a listener at each event occurred in employeesAdded stream).



                  @override
                Widget build(BuildContext context) {
                return Scaffold(
                body: Builder(
                builder: (BuildContext context) {
                bloc.employeesAdded.listen(
                (_) {
                Scaffold.of(context).showSnackBar(
                SnackBar(
                content: Text('Employee added'),
                ), // SnackBar
                );
                },
                );

                return _buildBody(bloc);
                },
                ), // Builder
                ); // Scaffold
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Mar 4 at 20:15









                idow09idow09

                7829




                7829






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54023203%2fflutter-snackbar-display-based-on-stream%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas