0

I am newbie in flutter so please let me know if i am wrong.In my application i have to logged in using facebook so i took a RawMaterialButton and in onPressed function in used following code

child: RawMaterialButton(
                    onPressed: () {
                      FutureBuilder<String>(
                        future:
                            _login(), // function where you call your api
                        builder: (BuildContext context,
                            AsyncSnapshot<String> snapshot) {
                          // AsyncSnapshot<Your object type>
                          print(snapshot);
                          if (snapshot.connectionState ==
                              ConnectionState.done) {
                            print('${snapshot.data}');
                          }
                          if (snapshot.connectionState ==
                              ConnectionState.waiting) {
                            return Center(
                                child: Text('Please wait its loading...'));
                          } else {
                            if (snapshot.hasError)
                              return Center(
                                  child: Text('Error: ${snapshot.error}'));
                            else
                              return Center(
                                  child: new Text(
                                      '${snapshot.data}')); // snapshot.data  :- get your object which is pass from your downloadData() function
                          }
                        },
                      );
                      return CircularProgressIndicator();
                    },

when i press the button its calling the method and i am getting data but after getting those data future building is not updating or showing that data in a Text.here is my data fetch method.

  Future<String> _login() async {
final result = await FacebookAuth.instance.login();
var tokenString;
switch (result.status) {
  case FacebookAuthLoginResponse.ok:
    _printCredentials(result);
    // get the user data
    // final userData = await FacebookAuth.instance.getUserData();
    tokenString = result.accessToken.token;
    break;
  case FacebookAuthLoginResponse.cancelled:
    print("login cancelled");
    tokenString = "User cancelled";
    break;
  default:
    tokenString = "Login failed";
}
return tokenString;
}

For debug purpose i made break point also but its not directing to the asynchronous snapshot condition state checking.I could not find out the reasons. I also check following stack question also.

Why FutureBuilder doesn't get call in Flutter? Flutter FutureBuilder Not Updating

Emon
  • 452
  • 3
  • 11
  • 21

1 Answers1

1

Well, in your onPressed function you are declarating a FutureBuilder and it's definitly wrong. FutureBuilder allows you to make an asynchronous request for a function or method to use the response data to build a widget or another depending of the snapshot value. This happens when you run the widget for the first time or use SetState({}) in a StatefulWidget. But you are joining view code with functional code. This is the way to implement a FutureBuilder:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _login(),
      builder: (context, snapshot) {
        print(snapshot);
        if (snapshot.connectionState == ConnectionState.done) {
          print('${snapshot.data}');
        }
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: Text('Please wait its loading...'));
          // Or return CircularProgressIndicator();
        } else {
          if (snapshot.hasError)
            return Center(child: Text('Error: ${snapshot.error}'));
          else
            return Center(
                child: new Text(
                    '${snapshot.data}'));
        }
      },
    );
    // if you return something here, it's dead code
  }

But i would suggest you to implement FutureBuilder in this way:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: FutureBuilder(
        future: _login(),
        builder: (context, snapshot) {
          if (snapshot.hasError) // if it has error
            return Text('Error: ${snapshot.error}');
          if (!snapshot.hasData) {
            // if it's loading
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('Please wait its loading...'),
                Padding(
                  padding: EdgeInsets.only(top: 20),
                  child: Container(
                    height: 35,
                    width: 35,
                    child: CircularProgressIndicator(),
                  ),
                ),
              ],
            );
          } else {
            // if everything success
            print(snapshot.data);
            return Text('${snapshot.data}');
          }
        },
      ),
    );
  }

Finally, what i think you want is use a Provider to create a comunication way between widgets into your login page because you want to change the State of the page/view widget by pressing a button, u could use a StatefulWidget but u should see this tutorial better. and here is the provider documentation.

Pdst: But, if u don't want to implement provider you could make the _login() request in the button like:

onPressed: () async {
  String response = await _login();
  Navigator.push(context, MaterialPageRoute(builder: (context) => ResponseWidget(response)));
}

With navigator.push() you can change the view/page/widget that u have in your screen and show a new widget that could show something deppending the response value.

José Luna
  • 307
  • 3
  • 4
  • 1
    May be thats how community will increase for flutter.Thanks is not enough for you.Anyway Thanks :) – Emon Oct 26 '20 at 20:38