2

I try to get current location my device and use it in initialCameraPosition,

The function is executed and I get the coordinates and set it in _currentPosition

After starting the screen i have an error:

LateError (LateInitializationError: Field 'currentPosition' has not been initialized.)

I think, map is created faster than the data is written to the variable, but i dont know how it fix.

Thanks fo help or advice how make code is correct


import 'package:flutter/material.dart';

import 'package:google_maps_flutter/google_maps_flutter.dart';

import 'package:geolocator/geolocator.dart';

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

  @override
  State<UserMapInfo> createState() => _UserMapInfoState();
}

class _UserMapInfoState extends State<UserMapInfo> {
  late GoogleMapController mapController;

  late LatLng _currentPosition;

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

  getLocation() async {
    LocationPermission permission;
    permission = await Geolocator.requestPermission();

    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);
    double lat = position.latitude;
    double long = position.longitude;

    LatLng location = LatLng(lat, long);

    setState(() {
      _currentPosition = location;
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Map'),
      ),
      body: GoogleMap(
        onMapCreated: _onMapCreated,
        initialCameraPosition: CameraPosition(
          target: _currentPosition,
          zoom: 16.0,
        ),
      ),
    );
  }
}

Update

I try to use

LatLng? _currentPosition;

and add test coordinates

LatLng basePosition = LatLng(56.324293441187315, 38.13961947281509);

and add "null check"

my code


class _UserMapInfoState extends State<UserMapInfo> {
  
  late GoogleMapController mapController;

  // late LatLng currentPosition;

  LatLng? _currentPosition;

  LatLng basePosition = LatLng(56.324293441187315, 38.13961947281509);

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

  getLocation() async {
    LocationPermission permission;
    permission = await Geolocator.requestPermission();

    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);
    double lat = position.latitude;
    double long = position.longitude;

    LatLng location = LatLng(lat, long);

    setState(() {
      _currentPosition = location;
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Map'),
      ),
      body: GoogleMap(
        onMapCreated: _onMapCreated,
        initialCameraPosition: CameraPosition(
          target: _currentPosition ?? basePosition,
          zoom: 16.0,
        ),
      ),
    );
  }
}

And when my map is open, use LatLng basePosition ((( this is not what i need

I try other null check


initialCameraPosition: CameraPosition(
          target: _currentPosition!,
          zoom: 16.0,
        ),

ERROR again

_CastError (Null check operator used on a null value)

Thanks! Good solution!

And i`m add "null check" there

final code


import 'package:flutter/material.dart';

import 'package:google_maps_flutter/google_maps_flutter.dart';

import 'package:geolocator/geolocator.dart';

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

  @override
  State<UserMapInfo> createState() => _UserMapInfoState();
}

class _UserMapInfoState extends State<UserMapInfo> {
  late GoogleMapController mapController;

  LatLng? _currentPosition;

  bool _isLoading = true;

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

  getLocation() async {
    LocationPermission permission;
    permission = await Geolocator.requestPermission();

    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);
    double lat = position.latitude;
    double long = position.longitude;

    LatLng location = LatLng(lat, long);

    setState(() {
      _currentPosition = location;
      _isLoading = false;
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Map'),
      ),
      body: _isLoading
          ? const Center(
              child: CircularProgressIndicator(),
            )
          : GoogleMap(
              onMapCreated: _onMapCreated,
              initialCameraPosition: CameraPosition(
                target: _currentPosition!,
                zoom: 16.0,
              ),
            ),
    );
  }
}


Sergey M
  • 35
  • 1
  • 6

3 Answers3

1

Try this:

class _UserMapInfoState extends State<UserMapInfo> {
  
  late GoogleMapController mapController;

  LatLng? _currentPosition;
  bool _isLoading = true;

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

  getLocation() async {
    LocationPermission permission;
    permission = await Geolocator.requestPermission();

    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);
    double lat = position.latitude;
    double long = position.longitude;

    LatLng location = LatLng(lat, long);

    setState(() {
      _currentPosition = location;
      _isLoading = false;
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Map'),
      ),
      body: _isLoading ? 
      Center(child:CircularProgressIndicator()) : 
      GoogleMap(
        onMapCreated: _onMapCreated,
        initialCameraPosition: CameraPosition(
          target: _currentPosition,
          zoom: 16.0,
        ),
      ),
    );
  }
}
Georgina
  • 764
  • 2
  • 13
0

This is happening because getLocation() is a async method and you have to wait for it to finish before creating your map widget with _currentPosition

Below code is a quick solution:

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

  @override
  State<MapPage> createState() => _MapPageState();
}

class _MapPageState extends State<MapPage> {
  late GoogleMapController mapController;
  late Future _getCurrentLocationFuture;
  LatLng? _currentPosition;

  @override
  void initState() {
    _getCurrentLocationFuture = _getCurrentLocation();
    super.initState();
  }

  _getCurrentLocation() async {
    Position position;
    try {
      position = await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high,
          forceAndroidLocationManager: true,
          timeLimit: Duration(seconds: 15));
    } catch (e) {
      position = null;
      debugPrint(e);
    }

    if (position != null) {
      LatLng location = LatLng(position.latitude, position.longitude);
      _currentPosition = location;
    }

    return true;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
        future: _getCurrentLocationFuture,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return GoogleMap(
              onMapCreated: _onMapCreated,
              initialCameraPosition: CameraPosition(
                target: _currentPosition ??
                    LatLng(56.324293441187315, 38.13961947281509),
                zoom: 16.0,
              ),
            );
          } else {
            return CircularProgressIndicator();
          }
        },
      ),
    );
  }

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

Also its best to check location permission and service before opening MapPage. or you can check it inside MapPage and then use animateCamera to move the map to current location

Ali Izadyar
  • 140
  • 1
  • 2
  • 13
0

We can achieve in simple way with Flutter_map without google map api key

Use Flutter_map and pass single or multiple latitude and longitude to mark in map

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';

class MapWidget extends StatelessWidget {
      final double latitude;
      final double longitude;
      const MapWidget({super.key, required this.latitude, required this.longitude});
    
      @override
      Widget build(BuildContext context) {
        return FlutterMap(
          options: MapOptions(
            maxZoom: 15,
            minZoom: 15,
            enableScrollWheel: false,
            center: LatLng(latitude, longitude),
            zoom: 15,
          ),
          children: [
            TileLayer(
              urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
              userAgentPackageName: 'com.example.app',
            ),
            MarkerLayer(
              markers: [
                Marker(
                  point: LatLng(latitude, longitude),
                  width: 80,
                  height: 80,
                  builder: (context) => IconButton(
                    onPressed: () => MapUtils().openMap(latitude, longitude),
                    icon: const Icon(
                      Icons.location_on,
                      color: Colors.blue,
                      size: 35,
                    ),
                  ),
                ),
              ],
            )
          ],
        );
      }
    }

Showing location based latitude and longitude

Rahul Raj
  • 1,010
  • 9
  • 10