Flutter LateInitializationError, although initialized

Viewed 31

Hey there StackOverflow community,

I am new to programming and started learning flutter/dart by following the Flutter Course from Angela Yu on udemy.

Currently at lecture 148. Getting Actual Weather Data from the OpenWeather API

The Goal: my code is supposed to return me the latitude, longitude, and my CityName Value. (e.g 285.7, 803, Cupertino)

The Problem: I am getting the LateInitialized error (see in code below), although I initialize them from my understanding. I tried using '?' ( double? latitudeLocation; double? longitudeLocation; double? latitude; double? longitude;) but then when printing flutter tells me that the variables are null, and I get the http error message 400.

The error message: "E/flutter ( 5529): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: LateInitializationError: Field 'latitudeLocation' has not been initialized. E/flutter ( 5529): #0 Location.latitudeLocation (package:clima_flutter_master/services/location.dart) E/flutter ( 5529): #1 _LoadingScreenState.getLocation (package:clima_flutter_master/screens/loading_screen.dart:23:25) E/flutter ( 5529): "

My Code: flutter sdk: 2.17.6

//main.dart
import 'package:flutter/material.dart';
import 'package:clima_flutter_master/screens/loading_screen.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(),
      home: LoadingScreen(),
    );
  }
}

_______________________________________________________
//loading_screen.dart
import 'package:clima_flutter_master/services/location.dart';
import 'package:flutter/material.dart';
import 'package:clima_flutter_master/services/location.dart';
import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

const apiKey = 'a89551623de7f2e030c199c9ec9ae123';

class LoadingScreen extends StatefulWidget {
  @override
  _LoadingScreenState createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {
  late double latitude;
  late double longitude;

  void getLocation() async {
    Location location = Location();
    await location.getCurrentLocation;

    latitude = location.latitudeLocation;
    longitude = location.longitudeLocation;

    getData();
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getLocation();
  }

  void getData() async {
    http.Response response = await http.get(Uri.parse(
        'https://api.openweathermap.org/data/2.5/weather?lat=$latitude&lon=$longitude&appid=$apiKey'));
    print(response.statusCode);

    if (response.statusCode == 200) {
      String data = response.body;
      print(data);

      var decodedData = jsonDecode(data);

      double temperature = decodedData(data)['main']['temp'];
      print(temperature);

      int condition = decodedData['weather'][0]['id'];
      print(condition);

      String cityName = decodedData['name'];
      print(cityName);
    } else {
      print(response.statusCode);
    }
  }

  @override
  Widget build(BuildContext context) {
    getData();
    return Scaffold();
  }
}
_______________________________________________________
//location.dart
import 'package:geolocator/geolocator.dart';

class Location {
  late double latitudeLocation;
  late double longitudeLocation;

  Future<void> getCurrentLocation() async {
    try {
      Position position = await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.low);

      latitudeLocation = position.latitude;
      longitudeLocation = position.longitude;
    } catch (error) {
      print(error);
    }
  }

  void getLocation() async {
    bool serviceEnabled;
    LocationPermission permission;

    // Test if location services are enabled.
    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      // Location services are not enabled don't continue
      // accessing the position and request users of the
      // App to enable the location services.
      return Future.error('Location services are disabled.');
    }

    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        // Permissions are denied, next time you could try
        // requesting permissions again (this is also where
        // Android's shouldShowRequestPermissionRationale
        // returned true. According to Android guidelines
        // your App should show an explanatory UI now.
        return Future.error('Location permissions are denied');
      }
    }

    if (permission == LocationPermission.deniedForever) {
      // Permissions are denied forever, handle appropriately.
      return Future.error(
          'Location permissions are permanently denied, we cannot request permissions.');
    }
  }
}

I am grateful for everyone who could help!

1 Answers

The problem is that getData is being called in the build method. getData is already called getLocation.

  @override
  Widget build(BuildContext context) {
    getData(); // <- Remove this line
    return Scaffold();
  }

If you need to wait for getLocation to finish in the build method use a FutureBuilder like so:

class _LoadingScreenState extends State<LoadingScreen> {
  late double latitude;
  late double longitude;
  late Future future;

  Future<void> getLocation() async {
    Location location = Location();
    await location.getCurrentLocation;

    latitude = location.latitudeLocation;
    longitude = location.longitudeLocation;

    await getData();
  }

  @override
  void initState() {
    super.initState();
    future = getLocation();
  }

  void getData() async {
    http.Response response = await http.get(Uri.parse(
        'https://api.openweathermap.org/data/2.5/weather?lat=$latitude&lon=$longitude&appid=$apiKey'));
    print(response.statusCode);

    if (response.statusCode == 200) {
      String data = response.body;
      print(data);

      var decodedData = jsonDecode(data);

      double temperature = decodedData(data)['main']['temp'];
      print(temperature);

      int condition = decodedData['weather'][0]['id'];
      print(condition);

      String cityName = decodedData['name'];
      print(cityName);
    } else {
      print(response.statusCode);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
        future: future,
        builder: (context, snapshot) {
          if (snapshot.hasError) {
            return const Center(child: Text('Error getting location data'));
          }

          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          }

          // do something...
        },
      ),
    );
  }
}
Related