setState() callback argument returned a Future - flutter

I am new in flutter and stuck with this issue. Any one help me
setState() callback argument returned a Future. The setState() method on _SingupPageState#7bfa9 was called with a closure or method that returned a Future. Maybe it is marked as "async".
setState(() async {
String url = 'http://192.168.43.91:8000/api/signup';
var json = jsonEncode({
"name": name.text.toString(),
"email": email.text.toString(),
"password": password.text.toString(),
});
Response response = await post(url,
headers: {"Content-Type": "application/json"}, body: json);
// Map<String, dynamic> user = jsonDecode(response.body);
if(response.statusCode==200){
print('success');
}
else{
print('not success');
}
}
);

you should write something like that:
onTap:() async{
setState((){
//what you want to do } }

Here you are trying to make post request, this kind of method's return type should be future, try to first get the result by defining then use the response statusCode to use setState i mean :
in case of having a RaisedButton Widget your code should look like that :
onTap : () async {
await //call your http,
setSatet((){
//somecode base on http result
})

Related

Flutter Http getting a response but passing null to then when the method is call

I actually get the response from my API, using this method.
static Future<String> saveData(String url, Vehicle vehicle) async {
dio.Dio d = dio.Dio();
Map<String, dynamic> headers = {};
headers['Cookie'] = "JSESSIONID=" + "fff";// SessionUtils().getSession().toString();
dio.Options options = dio.Options(
headers: headers,
contentType: 'application/json',
responseType: dio.ResponseType.json,
);
final dio.Response response = await d.post(url, options: options, data: jsonEncode(vehicle));
print(response.data);
dynamic item;
String result = "";
if (response.statusCode == HttpStatus.ok) {
item = response.data; //json.decode(response.data);
print("****************");
print(item);
print("****************");
print(item["id"]);
if(item["success"]){
result = item["id"]; // **result is correct here**
print("OK");
}
print(item["success"]); // Data is printed out correctly
}
print(result);
return result;
}
But when I call this method using the code below I cannot get the returned data in the then.
VehicleHttpService.saveData(Constant.POST_VEHICLE_URL, widget.vehicle).then((value){
}).then((String? value){
print("#########");
print(value); //**I get null here. why**
print("#########");
}).whenComplete((){
Navigator.of(context).pop();
});
I was expecting the result returned by saveData. Please help me check what is wrong with my code.
Let's check your executing code by parts:
VehicleHttpService.saveData(Constant.POST_VEHICLE_URL, widget.vehicle).then((value){
}).then((String? value){
print("#########");
print(value); //**I get null here. why**
print("#########");
}).whenComplete((){
Navigator.of(context).pop();
});
The first step is executing the API request and return a response
VehicleHttpService.saveData(Constant.POST_VEHICLE_URL, widget.vehicle)
The second step is receives the response, converts it in null and return to the Future chain
then((value){})
The third step always will receive the null
then((String? value){
print("#########");
print(value); //**I get null here. why**
print("#########");
}).whenComplete((){
Navigator.of(context).pop();
})
Remove then in the middle and you will receive the response and can able to handle it

Unable to use a Future value - Flutter/Dart

I've fetched a json object and deserialized it and then returned it too.
I want to use this in another file.
I'm unable to assign the values that I'm getting in the first step.
Here are all the codes...
Service
Future getGeoPoints(String accessToken, String tripId) async {
String requestUrl;
var response = await get(
Uri.parse(requestUrl),
headers: {
'Authorization': "Bearer $accessToken",
},
);
if (response.statusCode == 200) {
Map<String, dynamic> responseBody = json.decode(response.body);
GetGeoPoints geoPoints = GetGeoPoints.fromJson(responseBody);
List listOfGeoPoints = [];
for (var geoPoint in geoPoints.geoPoints) {
listOfGeoPoints.add(
{
'latitude': geoPoint.latitude,
'longitude': geoPoint.longitude,
'timestamp': geoPoint.timeStamp,
},
);
}
// print('List of geo points: ' + '$listOfGeoPoints');
return listOfGeoPoints;
} else {
throw Exception('Failed to load data from server');
}
}
File where I need the above values
List routeCoordinates;
Future<void> getValues() async {
getGeoPoints(widget.accessToken, widget.tripId)
.then((value) => routeCoordinates = value);
}
When I run the app, routeCoordinates is null but when I hotreload, it contains the value.
I want to have the values as soon as the screen starts. What is the right way to assign the values here?
I've also tried this:
routeCoordinates = getGeoPoints...
It throws error..
Please help.. Thanks..
The function getGeoPoints() is an asynchronous one. But on the other file, you are not using the await keyword, instead you are using then(). So your code is not waiting for that function to return value.
Try using below code,
List routeCoordinates;
Future<void> getValues() async {
routeCoordinates = await getGeoPoints(widget.accessToken, widget.tripId);
}
Let us know how it went.
You need to use a FutureBuilder to define a behaviour depending on the state of the request. You'll be able to tell the widget what to return while your app is waiting for the response to your request. You can also return a specific widget if you get an error(if your user is offline, for example).
Edit: I've linked the official docs but give this article a read if it's not clear enough.

How can I return a Future from a stream listen callback?

I have below code in flutter:
getData() {
final linksStream = getLinksStream().listen((String uri) async {
return uri;
});
}
In getData method, I want to return the value of uri which is from a stream listener. Since this value is generated at a later time, I am thinking to response a Future object in getData method. But I don't know how I can pass the uri as the value of Future.
In javascript, I can simply create a promise and resolve the value uri. How can I achieve it in dart?
In your code 'return uri' is not returning from getData but returning from anonymous function which is parameter of listen.
Correct code is like:
Future<String> getData() {
final Completer<String> c = new Completer<String>();
final linksStream = getLinksStream().listen((String uri) {
c.complete(uri);
});
return c.future;
}
Try this
Future<String> getData() async{
final linksStream = await getLinksStream().toList();
return linksStream[0].toString();
}

The method '[]' was called on null in Flutter

i want to get the data returned from a method 'getData()' into a List 'datat' but i am getting this error
: ' The method '[]' was called on null '
this is the corresponding code :
ListeMedecinsState() {
/* Fetching Data Into ListView */
Future<String> getData() async {
var response = await http.get(
Uri.encodeFull("http://10.0.2.2:4000/user/GetAllMedecins"),
headers: {
"Accept": "application/json"
}
);
this.setState(() {
this.data = json.decode(response.body);
});
return "Success";
}
getData() ;
print(this.data[1]["email"]);
/* Fetching Data Into ListView */
}
Notice : when i retreive the data into the list inside the method it shows no error, i want to use the data outside of the method scope how can i do please ?
Also, you could do it this way:
getData().then((data){
//do something with data
});
You should await getData();
But please post your full code so it's more understandable.
Thank you
#Sebastian is correct. (so select his answer not mine. I'm only posting here so that you can see the complete code) Your code should read:
ListeMedecinsState() async { // <-- this has to be added as well
/* Fetching Data Into ListView */
Future<String> getData() async {
var response = await http.get(
Uri.encodeFull("http://10.0.2.2:4000/user/GetAllMedecins"),
headers: {
"Accept": "application/json"
}
);
this.setState(() {
this.data = json.decode(response.body);
});
return "Success";
}
await getData() ; // <--- your code needs to pause until the Future returns.
print(this.data[1]["email"]);
/* Fetching Data Into ListView */ }
As Sebastian said, your ListeMedecinState should be asynchronous.
So that you can await the request and only proceed on it completion.
Your code actually doesn't wait for the result of getData() method before proceeding.
So you should await it before trying to access the data fetched !
Hope this helps !
(Seems like you speak French, I speak French too just in case you get lost) :)

Building widget in Flutter when response statusCode on API call is >400

So I'm trying to call the REST API for the login here. This is in my api_services.dart where I am calling all the APIs for the application.
api_services.dart
Future<User> loginUser(String email, String password)
async {
final response = await http.post(serverOauthUrl+'/token',
headers: {
HttpHeaders.AUTHORIZATION: "xxxx"
},
body: {
"email":"$email",
"password":"$password",
}
);
print(response.statusCode);
final responseJson = json.decode(response.body);
return new User.fromJson(responseJson);
}
And there are two ways I can call this loginUser() method in my UI files and get the response. One that uses the then() method and the other uses FutureBuilder. However, in none of the method, can I get the status code. My use case is that when the status code is >400, I will build a widget that shows the error message.
login_screen.dart
then() method code:
_callLoginAPI(String email, String password){
loginUser(userName, password, "password").then((response) {
response.data.token;
// want my status code here as well along with response data
}
else
{
//todo show something on error
}
}, onError: (error) {
debugPrint(error.toString());
});
}
Or using FutureBuilder :
return new FutureBuilder<User>(
future: loginUser(email, password),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(snapshot.data.token);
} else if (snapshot.hasError) {
print(snapshot.error);
return new Text("${snapshot.error}");
}
return new CircularProgressIndicator();
},
);
What I want to do is something like this
if(response.statusCode > 400)
return new Text("Error"):</code>
Thanks to #Thomas, this issue is resolved. Was an easy solution actually.
Adding the changes in the code for other beginners to follow :
api_services.dart
Future<http.Response> loginUser(String email, String password) async {
final response = await http.post(serverOauthUrl+
'/token',
headers: {
HttpHeaders.AUTHORIZATION: "Basic xxx"
},
body: {
"email":"$email",
"password":"$password",
}
);
return response;
}
So instead of the User, I'm returning the http.Response object and now I can retrieve all the required info from the UI files.
Like this:
final responseJson = json.decode(response.body);
User user = User.fromJson(responseJson);
print(user.userName);
Hope it helps somebody
Why aren't you return an Api Result object instead of a user that contains the error code and the user?
Then you can build different widgets on your FutureBuilder depending on the status code.