when i run my code it gives error code 400 but when i do hot refresh it shows data in console while getting data from api in flutter
it means API needs time to send data but my code is not waiting I am using async await too but still
please help if u can
here im trying to fetch data
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:weather_app/services/location.dart';
import 'package:weather_app/utilities/constants.dart';
class LoadingScreen extends StatefulWidget {
@override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
double latitude;
double longitude;
@override
void initState() {
super.initState();
getLocation();
}
void getLocation() async {
GettingLocation gettingLocation = GettingLocation();
await gettingLocation.getCurrentPosition();
lattitude = gettingLocation.latitude;
longitude = gettingLocation.longitude;
}
void getData() async {
http.Response response = await http.get(Uri.parse(
'https://api.openweathermap.org/data/2.5/weather?lat=$lattitude&lon=$longitude&appid=$apiKey'));
if (response.statusCode == 200) {
String data = response.body;
print(data);
} else {
print(response.statusCode);
}
}
@override
Widget build(BuildContext context) {
getData();
return Scaffold();
}
}
This is location.dart
import 'package:geolocator/geolocator.dart';
class GettingLocation {
double latitude;
double longitude;
Future<void> getCurrentPosition() async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.low);
latitude = position.latitude;
longitude = position.longitude;
} catch (e) {
print(e);
}
}
}
The problem is not that the API needs time to return data, the problem is the order in which asynchronous methods execute.
This is the order of execution for what you show:
initState -> build -> getData -> getLocation
So by the time getData executes, getLocation is not done executing, so latitude and longitude don't have the correct values. When you run hot reload
, only build
and getData
execute again, so the code works.
The simplest way to fix this is to move the call to getLocation
into getData
directly, but this means the data will take longer to fetch because the getPosition
will only start executing when you execute getData
.
First, remove getPosition
from initState
, then, on getData
void getData() async {
await getLocation(); // <------ this line
http.Response response = await http.get(Uri.parse(
'https://api.openweathermap.org/data/2.5/weather?lat=$lattitude&lon=$longitude&appid=$apiKey'));
if (response.statusCode == 200) {
String data = response.body;
print(data);
} else {
print(response.statusCode);
}
}
It is also worth mentioning that both getData
and getLocation
have a return type of void
, this can have unexpected consequences when dealing with async callbacks, I recommend you replace it with Future<void>
Future<void> getLocation() { ... }
Future<void> getData() { ... }
Finally, as I said this solution has the slight disadvantage that the call to getLocation
is moved into later, in practice there shouldn't be any problem with this, because the difference in time should be minuscule, but still I made an example using FutureBuilder
that will display the getData
data:
class LoadingScreen extends StatefulWidget {
@override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
double latitude;
double longitude;
late Future<void> _locationFuture;
@override
void initState() {
super.initState();
_locationFuture = getLocation();
}
Future<void> getLocation() async {
GettingLocation gettingLocation = GettingLocation();
await gettingLocation.getCurrentPosition();
lattitude = gettingLocation.latitude;
longitude = gettingLocation.longitude;
}
Future<String?> getData() async {
await _locationFuture;
http.Response response = await http.get(Uri.parse(
'https://api.openweathermap.org/data/2.5/weather?lat=$lattitude&lon=$longitude&appid=$apiKey'));
if (response.statusCode == 200) {
return response.body;
print(data);
} else {
print(response.statusCode);
}
}
@override
Widget build(BuildContext context) {
return FutureBuilder<String?>(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasData) return Text(snapshot.data!);
return CircularProgressIndicator();
}
);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.