i am confused where can i implement the init state condition for future builder. see whats wrong in my code. in flutter documentation is refer initState for Future builder widget.
` @override
void initState() {
super.initState();
futureLoginuser = loginuser();
}`
i am trying to navigate new screen after response data arrives.my complete code is here i am using go_router for navigation.
class LoginForm extends StatefulWidget {
const LoginForm({Key? key}) : super(key: key);
@override
LoginFormState createState() {
return LoginFormState();
}
}
class LoginFormState extends State<LoginForm> {
TextEditingController mobileController = TextEditingController();
TextEditingController passwordController = TextEditingController();
final _mobileKey = GlobalKey<FormState>();
final _passwordKey = GlobalKey<FormState>();
get message => null;
get messagecode => null;
get userinfo => null;
get token => null;
Future<Loginuser> loginuser(String mobile, String password) async {
final response = await http.post(
Uri.parse('https:random.url/api/login'),
body: {'mobile': mobile, 'password': password});
if (response.statusCode == 200) {
return Loginuser.fromJson(jsonDecode(response.body));
}
} else {
throw Exception('Failed to update');
}
@override
Widget build(BuildContext context) {
return Form(
key: _mobileKey,
child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
TextFormField(
controller: mobileController,
autofocus: true,
keyboardType: TextInputType.phone,
decoration: const InputDecoration(
border: InputBorder.none,
hintText: "Enter Your Mobile Number",
),
),
TextFormField(
controller: passwordController,
key: _passwordKey,
keyboardType: TextInputType.visiblePassword,
decoration: const InputDecoration(
border: InputBorder.none,
hintText: "Enter Your Password",
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
FutureBuilder<Loginuser>(
future: loginuser(mobileController.text.toString(),
passwordController.text.toString()),
builder: (context, snapshot) {
if (snapshot.hasData) {
print('snapshsot.hasdata');
context.go('/Home');
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
child: const Text('Submit')),
),
]));
}
}
`
CodePudding user response:
You are using the FutureBuilder
wrong it is a Widget that builds itself based on the latest snapshot of interaction with a Future. Its usually used to build widgets that need input when a certain future is completed.
In your case use this:
//first make the onPressed function async
child ElevatedButton(
child: Container(),
onPressed: () async {
// then await the future You want to complete and then use `.then()`
//method to implement the code that you want to implement when the future is completed
await loginuser(mobileController.text.toString(),
passwordController.text.toString())
.then((result) {
print('future completed');
context.go('/Home');
// For errors use one rror to show or check the errors.
}).onError((error, stackTrace) {
print(error);
});
});
And do validate the form for any error with form key validation method.
the only way to wait for the future to complete and do something is to use the Asynchronous function either directly as I have shown above or by using the try/catch method both will work fine.
CodePudding user response:
Try this
LoginUser? loginUser
@override
void initState() async{
super.initState();
futureLoginuser = await loginuser();
... //