The method '[]' was called on null in Flutter - 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) :)

Related

http put did not send any response in flutter

Hey I have this app where I can update status, and I use http.put method, but it takes forever to response. I got this error
error
And here is the code for http.put
Future<void> mapEventToState(
Emitter<ReportStatusState> emit, ReportStatusEvent event) async {
emit(ReportStatusLoading());
ReportStatusPut statusPut = event.statusPutBody;
// ReportStatusModel model =
// await apiAuthRepository.updateReportStatus(statusPut, event.id);
ReportStatusModel model = await updateReportStatus({'biaya': '0', 'status': 'SELESAI'}, event.id);
print(model);
if (!model.success) {
emit(ReportStatusFailure(model.message));
}
print(model.code);
emit(ReportStatusSuccess());
}}
Future<ReportStatusModel> updateReportStatus(
Map data, String id) async {
final SharedPreferencesManager sharedPreferencesManager =
locator<SharedPreferencesManager>();
String? token =
sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessToken);
try {
final response = await http.put(
Uri.parse('https://api.komplekku.com/officer/api/report/v1/$id'),
body: json.encode(data),
headers: {'Authorization': 'Bearer $token'});
return ReportStatusModel.fromJson(json.decode(response.body));
} catch (e) {
throw Exception(e);
}
}
There is nothing wrong with the API, I already check using Postman and it worked perfectly fine, Anyone know what went wrong?

How to have a flutter class method return a future?

How do I set up a flutter method to return a future value that is drawn from the results of a future http post call inside the method?
The example code below is making a call to a web URL to add a new product. I want this method to return just the Id of the newly created product (i.e. 'name' inside response)
Future<String> add(Product aNewProduct) async {
var aUrl = Uri.parse(dbUrl);
http.post(aUrl,body: toBody(aNewProduct),).then((response) {
var aStr = json.decode(response.body)['name'];
return Future<String>.value(aStr);
});
}
With the code above, the parser is showing the following error/warning...
The body might complete normally, causing 'null' to be returned,
but the return type, 'FutureOr<String>', is a potentially non-nullable type.
(Documentation) Try adding either a return or a throw statement at the end.
Any suggestions on how to fix this?
You can use the await to get the value of a Future or rather your http request. After that you can simple decode it and return your desired behavior.
Future<String> add(Product aNewProduct) async {
var aUrl = Uri.parse(dbUrl);
final response = http.post(
aUrl,
body: toBody(aNewProduct),
);
return json.decode(response.body)['name'];
}
try this:
Future<String> add(Product aNewProduct) async {
var aUrl = Uri.parse(dbUrl);
var response= await http.post(aUrl,body: toBody(aNewProduct),);
if(response.statusCode==200){
var rawData = await response.stream.bytesToString();
Map data=json.decode(rawData);
return data['name'];
}else{
return '';
}
}
It is as simple as putting a return before the http.post statement

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