builder not been called when firing an api call using FutureBuilder

Issue

Im trying to call an api on login button tap, the api is been called, and is returning the right data, but the builder is not been called, neither the CircularProgressIndicator:

class _LoginState extends State<Login> {
  Future<LoginModel> getLoginData(String username, String password) async {
    var loginModel = await LoginAuthentication().login('name', 'pass');
    return loginModel;
  }


on button click im calling a widget

 void _loginTapped(BuildContext context) {
    buildLoginAPI(context);

  }

  Future<Widget> buildLoginAPI(BuildContext context) async {
    return FutureBuilder<LoginModel>(
      future:  getLoginData('',''),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasError) {
            return Center(
              child: Text(
                snapshot.error.toString(),
                textAlign: TextAlign.center,
                textScaleFactor: 1.3,
              ),
            );
          }
          //TODO: Handle data: store the tokens in preferences
          //  final result = snapshot.data?.body;
        } else {
          return const CircularProgressIndicator();
        }
        return const CircularProgressIndicator();
      },

    );
  }

Solution

I don’t understand exactly what you are trying to achieve here.
FutureBuilder is a widget that we use to wait for some data to be fetched and show something on the screen accordingly to that data.
I will assume You want to show data that is being fetched:
You should not put the FutureBuilder as a return from a function (buildLoginAPI in our case) but instead, you should put the FutureBuilder directly in your widgets tree ( In your scaffold body as an example )
This way the FutureBuilder will show data that is being fetched from the function getLoginData ( Note that you have to call the function so that the data get fetched, you can do that either by calling it in initState or by pressing a button )

Example:

//Here the FutureBuilder can be the body of a scaffold for example
return Scaffold(
body :FutureBuilder<LoginModel>(
  future:  getLoginData('',''),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.done) {
      if (snapshot.hasError) {
        return Center(
          child: Text(
            snapshot.error.toString(),
            textAlign: TextAlign.center,
            textScaleFactor: 1.3,
          ),
        );
      }
      //TODO: Handle data: store the tokens in preferences
      //  final result = snapshot.data?.body;
    } else {
      return const CircularProgressIndicator();
    }
    return const CircularProgressIndicator();
  },
 ),
);

and for the function getLoginData you can call it by pressing a button, Example:

ElevatedButton(
  child: Text("Fetch Data"),
  onPressed: ()=>getLoginData('',''),
  ),
          

Answered By – Oussama Belabbas

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.