Flutter Stream Builder Triggered when Navigator Pop or Push is Called

后端 未结 2 1015
我寻月下人不归
我寻月下人不归 2020-12-16 05:57

I have a stream builder in the app\'s home/root page. This stream builder gets triggered whenever I do a page-navigation elsewhere, which has nothing to do with the stream i

相关标签:
2条回答
  • 2020-12-16 06:21

    I spend hours figuring out how to fix this. Turns out AppHomePage need to extend StatefulWidget instead of StatelessWidget.

    No idea why, but it works.

    0 讨论(0)
  • 2020-12-16 06:37

    I can confirm that the build method in StreamBuilder is called every time we navigate within our app, which is not efficient since it should cancel its listener, create a new one and rebuild the entire widget.

    You may face that issue if your app listens to the authentication state in order to show an appropriate screen when auth state changes (Loading/Login/Home)

    So in most of the tutorials, you will see that StreamBuilder is created in the build method in a Stateless widget. This is not an efficient solution.

    Instead use Stateful widget and listen to your auth changes in initState() or didChangeDependencies() methods.

    The difference in our case would be that in initState() you will have issues in getting your Auth service if you use Provider (The context won't be ready with the Provided service yet). If you don't use Provider you can listen to changes in the initState(). But I highly recommend using Provider to separate your Services and Pages. In other words, use the MVVM pattern so your code will be scalable and maintainable.

    class LandingScreen extends StatefulWidget {
      @override
      _LandingScreenState createState() => _LandingScreenState();
    }
    
    class _LandingScreenState extends State<LandingScreen> {
      @override
      Widget build(BuildContext context) {
          return SplashView();
      }
    
      @override
      void didChangeDependencies() {
          //we don't have to close or unsubscribe SB
            Provider.of<AuthService>(context, listen: false).streamAuthServiceState().listen((state){
              switch (state) {
                case AuthServiceState.Starting:
                print("starting");
                  break;
                case AuthServiceState.SignedIn:
                  Navigator.pushReplacementNamed(context, Routes.HOME);
                  break;
                case AuthServiceState.SignedOut:
                  Navigator.pushReplacementNamed(context, Routes.LOGIN);
                  break;
                default:
                  Navigator.pushReplacementNamed(context, Routes.LOGIN);
              }
            });
    
        super.didChangeDependencies();
      }
    }
    

    If you'll use directly Firebase stream - replace my stream with FirebaseAuth.instance.onAuthStateChanged

    0 讨论(0)
提交回复
热议问题