简体   繁体   中英

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM