Atheer Alghamdi
Atheer Alghamdi

Reputation: 21

Flutter Error: StackOverflowError was thrown building Consumer<LocationProvider>(dirty, dependencies: [_InheritedProviderScope<LocationProvider?>])

i'm trying to include live location tracking into my app using the following packages:


I am receiving the following error:

════════ Exception caught by widgets library ═══════════════════════════════════
The following StackOverflowError was thrown building Consumer<LocationProvider>(dirty, dependencies: [_InheritedProviderScope<LocationProvider?>]):
Stack Overflow

The relevant error-causing widget was
Consumer<LocationProvider>
lib/google_map_page.dart:31
When the exception was thrown, this was the stack
#0      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#1      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#2      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#3      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#4      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#5      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#6      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#7      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#8      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#9      LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#10     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#11     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#12     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#13     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#14     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#15     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#16     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#17     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#18     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#19     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#20     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#21     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#22     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#23     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#24     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#25     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
#26     LocationProvider.locationPosition
package:map_test/provider/location_provider.dart:55
......

package:map_test/provider/location_provider.dart:55 --> LatLng get locationPosition => locationPosition;


There is 3 classes:

  1. main.dart
  2. google_map_page.dart
  3. location_provider.dart

1. main.dart

import 'package:flutter/material.dart';
import 'package:map_test/google_map_page.dart';
import 'package:map_test/provider/location_provider.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => LocationProvider(),
          child: const GoogleMapPage(),
        )
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        home: const GoogleMapPage(),
      ),
    );
  }
}

2. google_map_page.dart

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:map_test/provider/location_provider.dart';
import 'package:provider/provider.dart';

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

  @override
  State<GoogleMapPage> createState() => _GoogleMapPageState();
}

class _GoogleMapPageState extends State<GoogleMapPage> {
  @override
  void initState() {
    super.initState();
    Provider.of<LocationProvider>(context, listen: false).initalization();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Map2'),
          backgroundColor: Colors.red,
        ),
        body: googleMapUI());
  }

  Widget googleMapUI() {
    return Consumer<LocationProvider>(builder: (consumerContext, model, child) {
      if (model.locationPosition != null) {
        return Column(
          children: [
            Expanded(
              child: GoogleMap(
                mapType: MapType.normal,
                initialCameraPosition:
                    CameraPosition(target: model.locationPosition, zoom: 18),
                myLocationEnabled: true,
                myLocationButtonEnabled: true,
                onMapCreated: (GoogleMapController controller) {},
              ),
            )
          ],
        );
      }
      return Container(
        child: Center(
          child: CircularProgressIndicator(),
        ),
      );
    });
  }
}

3.location_provider.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';

class LocationProvider with ChangeNotifier {
  // Widget loc() {

  //   throw '';
  // }

  bool locationServiceActive = true;

  LocationProvider() {
    Location location;
    location = new Location();
  }
  Location get location => location;

  initalization() async {
    await getUserLocation();
  }

  getUserLocation() async {
    bool _serviceEnabled;
    PermissionStatus _permissionGranted;
    LatLng locationPosition;

    _serviceEnabled = await location.serviceEnabled();
    if (!_serviceEnabled) {
      _serviceEnabled = await location.requestService();
      if (!_serviceEnabled) {
        return;
      }
    }

    _permissionGranted = await location.hasPermission();
    if (_permissionGranted == PermissionStatus.denied) {
      _permissionGranted = await location.requestPermission();
      if (_permissionGranted != PermissionStatus.granted) {
        return;
      }
    }
    location.onLocationChanged.listen((LocationData currentLocation) {
      locationPosition = LatLng(
        currentLocation.latitude!,
        currentLocation.longitude!,
      );

      print(locationPosition);
      notifyListeners();
    });
  }

  LatLng get locationPosition => locationPosition; // line 55
}

It's my first time coding in flutter, i faced a lot of problem because of the Null Safety already. it just seems like the problems are endless. any recommendations will be much appreciated.

Thank you.

Upvotes: 2

Views: 3999

Answers (2)

V-SHY
V-SHY

Reputation: 4125

The StackOverflowError is caused by self reference

LatLng get locationPosition => locationPosition;

means locationPosition is itself. Hence will suggest you to amend the internal parameter variable by having prefix _

LatLng get locationPosition => _locationPosition;

while your class params and constructor can be written like below

class LocationProvider with ChangeNotifier {
  LatLng? _locationPosition;
  final Location _location = new Location();

  LocationProvider();

  Location get location => _location;

  LatLng? get locationPosition => _locationPosition;
  // other parts 
}

Upvotes: 2

Harsh Sureja
Harsh Sureja

Reputation: 1394

I am not sure but try to wrap consumer in build method Like this:

 @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Map2'),
          backgroundColor: Colors.red,
        ),
        body: Consumer<LocationProvider>(builder: (consumerContext, model, child) {
return googleMapUI()});
  }

And add needed parameters

Upvotes: 0

Related Questions