Search code examples
google-mapsflutterandroid-contextflutter-provider

Flutter GoogleMap Provider Context problem


I have a basic stateful app, with a GoogleMap base, which opens a BottomSheet on FloatingActionButton press. This is used as a settings tab to change/filter some lists which are then used by the map. My Provider is setup and values can be read/saved from both the GoogleMap dart file, and the BottomSheet dart file.

My main problem is how to provide context to the Provider.of() when not in the Widget Tree. For example, the GoogleMap runs onMapCreated: _onMapCreated, when finished loading. From within that function I want to pull a value from the Provider.of() a String, which tells me which list to use (which then populates the markers).

Things I'm trying to do:

  • onMapCreated() pull value from the Provider (which is later used in a DB sqflite query)
  • The bottomsheet needs to callback and updateMarkers() somehow, providing correct context
void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  GoogleMapController mapController;

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;

    print(Provider.of<MyAppStateContainer>(context, listen:false).getSomeValue);  <---- Doesn't work
  ...
}


@override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyAppStateContainer>(
      create: (contextooo) => MyAppStateContainer(),
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text('My Map'),
            backgroundColor: Colors.green[700],
          ),

          //Put in a stack widget so can layer other widgets on top of map widget
          body: Stack(
            children: <Widget>[
              //Builder so we can get a CTX made, and then Provider.of() finds the Provider
              Builder(
                builder: (context) => GoogleMap(
                  mapType: Provider.of<MyAppStateContainer>(context).getMapType, <--- Works fine
                  markers: _markers,
                  onMapCreated: _onMapCreated,

             ...
}

Provider:

class MyAppStateContainer extends ChangeNotifier {
  MyAppStateContainer();

  MapType _mapType = MapType.terrain;
  String _someValue;

  MapType get getMapType => _mapType;
  String get getSomeValue => _someValue;
}

I've tried all sorts of combinations of passing back BuildContext context but sadly I'm forever getting this error about the Widget Tree:

Unhandled Exception: Error: Could not find the correct Provider<MyAppStateContainer> above this MyApp Widget


Solution

  • The problem is that within _onMapCreated, you are trying to access the Provider using the context of MyApp, which is higher up the hierarchy of widgets than the Provider itself.

    Convert your home widget (the Scaffold and everything below it) into a separate StatefulWidget and everything should start working, as you'll be using the context of the new widget, which is lower down the hierarchy of widgets than the Provider.