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

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

Related

How to pass data from one table to another table using flutter (get and post on 2 different tables)?

I am creating an ecommerce Android flutter application, and I am new to this dart language. I need to get data from one table and post it to another table, where the API is built in .NET Core using a SQL Server database.
This is my code:
httpService.getPosts().then((value) {
if (value != null) {
value.forEach((element) {
httpServices.addPosts(
0,
element.cartProductID, element.productBrandId,
element.cartUserID, element.item,
element.quantity, element.price,
element.totalPrice,
element.discount,
// element.isOrdered,
element.paymentID,
element.paymentMode,
element.date,
);
});
My get method
class GetOrderHttpService with ChangeNotifier {
Future<List<OrderTotal>> getPosts() async {
Response res =
await http.get(Uri.https('********'));
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<OrderTotal> posts = body
.map(
(dynamic dynamic) => OrderTotal.fromJson(dynamic),
)
.toList();
notifyListeners();
return posts;
} else {
throw "Unable to retrieve posts.";
}
}
}
Future<bool> addPosts(
int orderID,
int orderProductID,
int productBrandId,
int orderUserID,
String item,
int quantity,
double price,
double totalPrice,
double discount,
int paymentID,
String? paymentMode,
DateTime date,
) async {
var response = await http.post(
Uri.https('************'),
body: jsonEncode({
'orderID': orderID,
'orderProductID': orderProductID,
'productBrandId': productBrandId,
'orderUserID': orderUserID,
'item': item,
'quantity': quantity,
'price': price,
'totalPrice': totalPrice,
'discount': discount,
'paymentID': paymentID,
'paymentMode': paymentMode,
'date': date
}),
headers: {
"Accept": "application/json",
"content-type": "application/json"
});
var data = response.body;
if (response.statusCode == 200) {
return true;
} else
throw Exception();
}
}
It successfully retrieves the data and passes it on to the future post method, but the database is not updated. When the breakpoint hits the post method, it doesn't go through the code and doesn't get any status code. Thank you
Notice you are using Future in both your get() and post() methods, but, when calling these methods you are not using the "await" keyword. You should use it every time you call a Future function assuring you are waiting that method to complete and retrieve data successfully. It might work without it (as you say your get method works) but, in more complex situations this might not be the case due to asynchronous nature of these type of functions.
Your code should look like this:
await httpService.getPosts().then((value) async {
if (value != null) {
value.forEach((element) {
await httpServices.addPosts(
0,
element.cartProductID, element.productBrandId,
element.cartUserID, element.item,
element.quantity, element.price,
element.totalPrice,
element.discount,
// element.isOrdered,
element.paymentID,
element.paymentMode,
element.date,
);
});
Hope this works. Have a nice day!

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.

Flutter - Before .then is executed, Function is returning the value and after that reading .then

I am facing 2 problems with the below code and I think both are related.
createFunction is showing an error -
"This function has a return type of 'FutureOr< bool >', but doesn't end with a return statement. Try adding a return statement, or changing the return type to 'void'." - I need to return true or false, so I have to use return type bool.
When the function is executed, it runs smoothly till the PROBLEM AREA (marked in the code). Here it returns null and then comes back to execute .then . I need to run .then right after http.post is executed. At the end of the code it should return true / false.
Any help will be highly appreciated.
Future<bool> createFunction(image) async {
var request = new http.MultipartRequest("POST", Uri.parse(_urlImage));
request.files.add(
await http.MultipartFile.fromPath('imagefile', image));
var response = await request.send().catchError((error) {
throw error;
});
response.stream.transform(utf8.decoder).listen((value) async {
return await http
.post(
_url,
headers: {
'content-type': 'application/json',
'authorization': 'auth'
},
body: json.encode({data}),
)
///// PROBLEM AREA //////
.then((value) async {
final _extractedData = await jsonDecode(value.body);
if (value.statusCode == 201) {
return true;
} else {
return false;
}
}).catchError((error) {
throw error;
});
});
}
Ok, for the next visitors to this page, the correct usage of MultipartRequest class should like this:
var uri = Uri.parse('https://example.com/create');
var request = http.MultipartRequest('POST', uri)
..fields['user'] = 'nweiz#google.com'
..files.add(await http.MultipartFile.fromPath(
'package', 'build/package.tar.gz',
contentType: MediaType('application', 'x-tar')));
var response = await request.send();
if (response.statusCode == 200) print('Uploaded!');

setState() callback argument returned a Future

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
})

Flutter - Give Index for dynamic http.post json response

I already have a button to fetch the API with function to ++increment index and set the new parameter on every click. My question is, how to set 'like a cache' for json response as index?
here my http.post request =
List<dynamic> _myResponse = [];
Future<void> trytoFetch(myIndex, parameter) async {
var url =
"https://jsonplaceholder.typicode.com/posts/$parameter";
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(url, headers: headers);
final responseJson = json.decode(response.body);
if (response.statusCode == 200) {
setState(() {
_myResponse[myIndex] = responseJson; // ITS DOESNT WORKS
});
} else {
setState(() {});
throw Exception('Failed to load internet');
}
}
My goal is like
if (response.statusCode == 200) {
setState(() {
_myResponse[0] = responseJson; // return responseJson from parameter
// Then I click the button with new parameter value and increment index
_myResponse[1] = responseJson; // return responseJson from new parameter
// Then I click the button with another new parameter value and increment index
_myResponse[2] = responseJson; // return responseJson from new parameter again
});
} else {
setState(() {});
throw Exception('Failed to load internet');
}
and in the end, I can simply print the returned json
print(_myResponse[0]);
print(_myResponse[1]);
print(_myResponse[2]);
How to achieve this? is it possible? Thanks
First of, you shouldn't pass index as a parameter to your method.
responseJson variable is a Map, you should convert that map to the object you need.
I suggest taking a look at this.