Q:

Auto navigation on login page in flutter app

My app needs to automatically initiate biometric login and navigate to a page based on outcome.
This is a common need and I followed advice similar to this solution
Code below
class _LoginPageState extends State<LoginPage> {
  @override
  Widget build(BuildContext context) {
    final UserModel userModel = Provider.of<UserModel>(context);

    return (userModel.biometricLoginEnabled && !userModel.isAuthenticated)
        ? _attemptBiometricAuthentication(context, userModel)
        : _buildLoginForm(context, userModel);
  }

  Widget _attemptBiometricAuthentication(
      BuildContext context, UserModel userModel) {
    return FutureBuilder(
      future: _initiateBiometricAuthentication(),
      builder: (context, snapshot) {
        if (snapshot.hasData && snapshot.data == true) {
          // make sure user is marked as authenticated
          userModel.setAuthenticationWithoutNotification(true);
          return HomePage(); // <-- WHOA!!
        } else if (snapshot.hasData && snapshot.data == false) {
          // we should have an updated error from _initiateBiometricAuthentication
          return _buildLoginForm(context, userModel);
        } else if (snapshot.hasError) {
          return _buildLoginForm(context, userModel);
        } else {
          // we're waiting
          return Container(
            constraints: BoxConstraints(
              maxHeight: MediaQuery.of(context).size.height,
              minHeight: MediaQuery.of(context).size.height,
            ),
            alignment: Alignment.center,
            child: SafeArea(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Image(
                    image: AssetImage('images/Logo.png'),
                    fit: BoxFit.fitWidth,
                  ),
                  CircularProgressIndicator(),
                ],
              ),
            ),
          );
        }
      },
    );
  }

}

The problem is with the line to return HomePage() if authentication succeeds.
If there is a call to setState() and a rebuild occurs I have the HomePage being rebuilt inside LoginPage.  Routing is also a little messed up because the app thinks it's on route /login but its actually on /home.
I feel like I'm missing something entirely in triggering routing automatically.

A:

You need to listen result from the Future method and navigate to other Page. (never do it inside build Widget).
Demo:

Code example:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class FutureNavigation extends StatefulWidget {
  @override
  _FutureNavigationState createState() => _FutureNavigationState();
}

class _FutureNavigationState extends State<FutureNavigation> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Demo Future Navigator"),
      ),
      body: buildBody(context),
    );
  }

  Widget buildBody(BuildContext context) {
    return FutureBuilder(
      future: _login(),
      builder: (context, snapshot) {
        return Center(child: CircularProgressIndicator());
      },
    );
  }

  Future<String> _login() async {
    await Future.delayed(Duration(seconds: 3)).then((value) {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(
          builder: (BuildContext context) {
            return HomePage();
          },
        ),
      );
    });

    return "Logined";
  }
}

