Search code examples
flutterdartflutter-layoutdart-null-safety

Lateinitializationerror field 'data' has not been initialized


I am new to flutter and I am trying to build an app which shows the current location by using Google Maps API. There is no error in this code but this error is coming after running: Exception has occurred. LateError (LateInitializationError: Field 'currentLocation' has not been initialized.)

Can someone please provide an example code of what's needed to solve for this error?

import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late GoogleMapController mapController;
  final Set<Marker> markers = {};
  // static const LatLng showLocation =
  late LatLng currentLocation;
  // late Widget googleMap;

  @override
  void initState() {
    super.initState();
    getCurrentPosition();
  }

  void getCurrentPosition() async {
    late Location location = Location();
    location.getLocation().then(
      (location) {
        currentLocation = location as LatLng; //as Future<APILocation>
      },
    );
  }

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
  }

  Future<Position> _determinePosition() 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.');
    }

    // When we reach here, permissions are granted and we can
    // continue accessing the position of the device.
    return await Geolocator.getCurrentPosition();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Position>(
        future: _determinePosition(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return const CircularProgressIndicator();
          }
          return GoogleMap(
            initialCameraPosition:
                CameraPosition(target: currentLocation, zoom: 15.0),
            markers: getmarkers(),
            mapType: MapType.normal,
            onMapCreated: (controller) {
              setState(() {
                mapController = controller;
              });
            },
          );
        });
  }

  Set<Marker> getmarkers() {
    setState(() {
      markers.add(
        Marker(
          markerId: MarkerId(currentLocation.toString()),
          position: currentLocation,
          infoWindow: const InfoWindow(
            title: 'Current Location',
            snippet: 'blabla',
          ),
          icon: BitmapDescriptor.defaultMarker,
        ),
      );
    });
    return markers;
  }
}

Solution

  • Change your getCurrentPosition like

    void getCurrentPosition() async {
      late Location location = Location();
      location.getLocation().then(
        (location) {
          currentLocation =
              LatLng(location.latitude ?? 0, location.longitude ?? 0); //this
        },
      );
    }
    

    There are others issue like

    • not using MaterialApp on root
    • using SetState on Build Time.
    • FutureBuilder on done returning CircularProgressBar
    • not sure what else I've changed, compare with your snippet
    import 'package:geolocator/geolocator.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    import 'package:location/location.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MaterialApp(home: const MyApp()));
    
    class MyApp extends StatefulWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      late GoogleMapController mapController;
      final Set<Marker> markers = {};
      // static const LatLng showLocation =
      //     LatLng(41.01358468198064, 28.86560382071653);
      late LatLng currentLocation;
      // late Widget googleMap;
    
      @override
      void initState() {
        super.initState();
        getCurrentPosition();
      }
    
      void getCurrentPosition() async {
        late Location location = Location();
        location.getLocation().then(
          (location) {
            currentLocation =
                LatLng(location.latitude ?? 0, location.longitude ?? 0);
          },
        );
      }
    
      void _onMapCreated(GoogleMapController controller) {
        mapController = controller;
      }
    
      Future<Position> _determinePosition() 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.');
        }
    
        // When we reach here, permissions are granted and we can
        // continue accessing the position of the device.
        return await Geolocator.getCurrentPosition();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: FutureBuilder<Position>(
              future: _determinePosition(),
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return const CircularProgressIndicator();
                }
    
                if (snapshot.hasError) return Text("Error");
    
                if (snapshot.hasData) {
                  return GoogleMap(
                    initialCameraPosition:
                        CameraPosition(target: currentLocation, zoom: 15.0),
                    markers: getmarkers(),
                    mapType: MapType.normal,
                    onMapCreated: (controller) {
                      mapController = controller;
                    },
                  );
                }
                return CircularProgressIndicator();
              }),
        );
      }
    
      Set<Marker> getmarkers() {
        markers.add(
          Marker(
            markerId: MarkerId(currentLocation.toString()),
            position: currentLocation,
            infoWindow: const InfoWindow(
              title: 'Current Location',
              snippet: 'blabla',
            ),
            icon: BitmapDescriptor.defaultMarker,
          ),
        );
    
        return markers;
      }
    }