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
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.