user10033434
user10033434

Reputation: 455

get location with geolocator and provider and flutter_maps

I'm trying to get the user current location with the geolocator plugin, and I'm using the provider package to handle the state. But I"m getting "initial location is null" error message. I'm using the flutter_maps package, not google maps.

I tried to look for a solution using the provider package, but i found none.

Here's my code:

main.dart:

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import './maps_module/map_states.dart';
import 'home_page.dart';


void main() {
  WidgetsFlutterBinding.ensureInitialized();
  return runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider.value(value: AppState())
      ],
      child: MyApp(),
    )
  );
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

home_page.dart:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:latlong/latlong.dart';
import 'package:geolocator/geolocator.dart';

import './maps_module/map_states.dart';
import './maps_module/maps_screen.dart';


class HomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    final appState = Provider.of<AppState>(context);

    return Scaffold(
      body: appState.initialPosition == null?
      Center(
        child: CircularProgressIndicator(),
      )
      :MapScreen(),
    );
  }
}

map_screen.dart:

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong/latlong.dart';

import 'map_states.dart';


class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => new _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {

  @override
  Widget build(BuildContext context) {

    final appState = Provider.of<AppState>(context);

    return SafeArea(
      child: Scaffold(
        // appBar: AppBar(),
        body: FlutterMap(
          mapController: appState.mapController,
          options: MapOptions(
            center: LatLng(appState.initialPosition.latitude, appState.initialPosition.longitude),
            minZoom: 10.0
          ),
          layers: [
            TileLayerOptions(
              urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
              subdomains: ['a','b','c']
            ),
            MarkerLayerOptions(
              markers: [
                Marker(
                  width: 80.0,
                  height: 80.0,
                  point: appState.initialPosition,
                  builder: (context) =>
                  Container(
                    child: IconButton(
                      icon: Icon(Icons.location_on),
                      color: Colors.redAccent,
                      iconSize: 45.0,
                      onPressed: (){print("hey");}
                    ),
                  )
                )
              ]
            )
          ],
        ),
      )
    );
  }
}

map_states:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

import 'package:flutter_map/flutter_map.dart';
import 'package:geolocator/geolocator.dart';
import 'package:latlong/latlong.dart';


class AppState with ChangeNotifier {

  bool locationServiceActive = true;

  MapController _mapController;
  MapController get mapController => _mapController;

  static var _initialPosition;
  var _lastPosition = _initialPosition;
  LatLng get initialPosition => _initialPosition;
  LatLng get lastPosition => _lastPosition;

  AppState(){
    checkGPS();
    _getUserLocation();
  }


  checkGPS() async{
    bool conn = await Geolocator().isLocationServiceEnabled();
    if(conn == false){
      locationServiceActive = false;
    } else {
      locationServiceActive = true;
    }
    notifyListeners();
  }

  void _getUserLocation() async{
    Position position = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    print("/////////////////////////////////////////////////////////////////////////////////position");
    print(position);

    _initialPosition = LatLng(position.latitude, position.longitude);
    notifyListeners();
  }
}

Upvotes: 4

Views: 2339

Answers (1)

wcyankees424
wcyankees424

Reputation: 2664

Your problem is that your are need to await checkgps() and _getUserLocation() in your class constructor the problem is your can't run asynchronous functions from the constructor of a class so you would need to do something like this. First of all you need to remove void from _getUserLocation() or make it Future<void> then add.

//Add to your class 
initalization() async {
    await _checkGPS();
    await getUserLocation();
  }

//This in a widget will prove it works
 @override
  void initState() {
    AppState().initalization();
    print('Location ${AppState().initialPosition}');
    super.initState();
  }

Upvotes: 2

Related Questions