flutter_map
flutter_map copied to clipboard
[BUG] LateInitializationError: Field '_interactiveViewerState' has already been initialized
What is the bug?
Error Message: LateInitializationError: Field '_interactiveViewerState@4245162146' has already been initialized.
LateInitializationError: Field '_interactiveViewerState@4245162146' has already been initialized.
StackTrace: {#0 LateError._throwFieldAlreadyInitialized (dart:_internal-patch/internal_patch.dart:184:5)
MapControllerImpl._interactiveViewerState= (package:flutter_map/src/map/controller/map_controller_impl.dart:19:40)
MapControllerImpl.interactiveViewerState= (package:flutter_map/src/map/controller/map_controller_impl.dart:47:7)
MapInteractiveViewerState.initState (package:flutter_map/src/gestures/map_interactive_viewer.dart:103:23)
StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5602:55)
ComponentElement.mount (package:flutter/src/widgets/framework.dart:5447:5)
Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
Element.updateChild (package:flutter/src/widgets/framework.dart:3831:20)
_LayoutBuilderElement._layout.layoutCallback (package:flutter/src/widgets/layout_builder.dart:132:18)
BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2835:19)
_LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:150:12)
RenderObject.invokeLayoutCallback. (package:flutter/src/rendering/object.dart:2657:59)
PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1071:15)
RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2657:14)
RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:225:7)
_RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:308:5)
RenderObject.layout (package:flutter/src/rendering/object.dart:2546:7)
RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:21)
RenderObject.layout (package:flutter/src/rendering/object.dart:2546:7)
RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
ChildLayoutHelper.layoutChild (package:flutter/src/rendering/layout_helper.dart:52:11)
RenderStack._computeSize (package:flutter/src/rendering/stack.dart:581:43)
RenderStack.performLayout (package:flutter/src/rendering/stack.dart:608:12)
RenderObject.layout (package:flutter/src/rendering/object.dart:2546:7)
RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:238:12)
RenderObject.layout (package:flutter/src/rendering/object.dart:2546:7)
RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:21)
RenderObject.layout (package:flutter/src/rendering/object.dart:2546:7)
RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:21)
RenderObject.layout (package:flutter/src/rendering/object.dart:2546:7)
RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
ChildLayoutHelper.layoutChild (package:flutter/src/rendering/layout_helper.dart:52:11)
RenderFlex._computeSizes (package:flutter/src/rendering/flex.dart:868:45)
RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:903:32)
RenderObject.layout (package:flutter/src/rendering/object.dart:2546:7)
RenderBox.layout (package:flutter/src/rendering/box.dart:2389:11)
MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:173:12)
_ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1062:7)
MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:237:7)
RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:403:14)
RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2385:7)
PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1025:18)
PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1038:15)
RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:591:23)
WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:986:13)
RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:457:5)
SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1325:15)
SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1255:9)
SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1113:5)
_invoke (dart:ui/hooks.dart:312:13)
PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:383:5)
_drawFrame (dart:ui/hooks.dart:283:31)
}
How can we reproduce it?
- Create a page with two TabBar
- Include FlutterMap in the first TabBar
- When navigating between tabs, the FlutterMap component will crash.
Do you have a potential solution?
_interactiveViewerState
Platforms
Android 13
Severity
Minimum: Allows normal functioning
Hi @astraube,
I could not reproduce this, using this code (adpated from the Flutter guide for working with tabs).
DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: const TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
title: const Text('Tabs Demo'),
),
body: TabBarView(
children: [
FlutterMap(
options: const MapOptions(
initialCenter: LatLng(51.5, -0.09),
initialZoom: 11,
),
children: [
openStreetMapTileLayer,
CircleLayer(
circles: [
CircleMarker(
point: const LatLng(51.5, -0.09),
color: Colors.blue.withOpacity(0.7),
borderColor: Colors.black,
borderStrokeWidth: 2,
useRadiusInMeter: true,
radius: 2000, // 2000 meters
),
CircleMarker(
point: const LatLng(51.4937, -0.6638),
// Dorney Lake is ~2km long
color: Colors.green.withOpacity(0.9),
borderColor: Colors.black,
borderStrokeWidth: 2,
useRadiusInMeter: true,
radius: 1000, // 1000 meters
),
],
),
],
),
Icon(Icons.directions_transit),
],
),
),
),
The only way for this error to occur is if the state of the internal map 'viewer' becomes detached from the state of the internal controller - which could cause the initState of one to be fired 'without' the other - which should not happen when using FM correctly.
Your fix might fix the issue for you for now, but it likely hides an issue with your usage - are you using it in some kind of other state which is not intialised/disposed of correctly?
Please check you are running the latest version of FM, and try using MapOptions.keepAlive if necessary. You may also need to try the keep alive mixin on any states above the map.
I'm getting this a lot as well. Not sure how to reproduce though. Sorry I don't have the whole stack but it was on the order of:
Exception caught by widgets library The following LateError was thrown building LayoutBuilder:
LateInitializationError: Field '_interactiveViewerState@1070162146' has already been initialized.
The relevant error-causing widget was: FlutterMap FlutterMap
We need an MRE to reproduce this. Similar issues in the past have been very hard to reproduce.
I would also suggest trying keepAlive, that might make a difference?
This can apparently be reproduced by providing a UniqueKey to the FlutterMap, then rebuilding.
Encountering this as well during a rebuild. This only happened after instantiating the MapController outside of the widget that used FlutterMap. The difference in my case is that I am not utilizing keys. FYI The code below results in a different exception/error, but this is essentially the same layout I have in my non-MRE, production app.
Exception
======== Exception caught by widgets library =======================================================
The following assertion was thrown building KeyedSubtree-[GlobalKey#05349]:
Should not update options unless they change
'package:flutter_map/src/map/controller/map_controller_impl.dart':
Failed assertion: line 342 pos 7: 'newOptions != value.options'
The relevant error-causing widget was:
Scaffold Scaffold:file:///home/joe/repos/bug/lib/main.dart:97:12
When the exception was thrown, this was the stack:
#2 MapControllerImpl.options= (package:flutter_map/src/map/controller/map_controller_impl.dart:342:7)
#3 _FlutterMapStateContainer._setMapController (package:flutter_map/src/map/widget.dart:188:22)
#4 _FlutterMapStateContainer.initState (package:flutter_map/src/map/widget.dart:61:5)
#5 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5611:55)
#6 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5456:5)
... Normal element mounting (28 frames)
#34 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4335:16)
#35 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6893:36)
#36 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6905:32)
... Normal element mounting (332 frames)
#368 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4335:16)
#369 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6893:36)
#370 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6905:32)
... Normal element mounting (688 frames)
#1058 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4335:16)
#1059 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6893:36)
#1060 Element.updateChild (package:flutter/src/widgets/framework.dart:3846:18)
#1061 Element.updateChildren (package:flutter/src/widgets/framework.dart:4033:32)
#1062 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6918:17)
#1063 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1064 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1065 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#1066 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1067 StatefulElement.update (package:flutter/src/widgets/framework.dart:5666:5)
#1068 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1069 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1070 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1071 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1072 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1073 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1074 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1075 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1076 _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:105:11)
#1077 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1078 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1079 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#1080 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1081 StatefulElement.update (package:flutter/src/widgets/framework.dart:5666:5)
#1082 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1083 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1084 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1085 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1086 _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:105:11)
#1087 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1088 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1089 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#1090 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1091 StatefulElement.update (package:flutter/src/widgets/framework.dart:5666:5)
#1092 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1093 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1094 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#1095 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1096 StatefulElement.update (package:flutter/src/widgets/framework.dart:5666:5)
#1097 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1098 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6765:14)
#1099 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1100 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6765:14)
#1101 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1102 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1103 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1104 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1105 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1106 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1107 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1108 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1109 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1110 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1111 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#1112 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1113 StatefulElement.update (package:flutter/src/widgets/framework.dart:5666:5)
#1114 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1115 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1116 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1117 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1118 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1119 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1120 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1121 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1122 _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:105:11)
#1123 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1124 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1125 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#1126 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1127 StatefulElement.update (package:flutter/src/widgets/framework.dart:5666:5)
#1128 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1129 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1130 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1131 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1132 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1133 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1134 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1135 StatelessElement.update (package:flutter/src/widgets/framework.dart:5556:5)
#1136 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1137 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1138 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1139 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1140 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1141 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1142 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1143 ProxyElement.update (package:flutter/src/widgets/framework.dart:5809:5)
#1144 Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#1145 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#1146 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#1147 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#1148 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2904:19)
#1149 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:989:21)
#1150 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:448:5)
#1151 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1386:15)
#1152 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1311:9)
#1153 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1169:5)
#1154 _invoke (dart:ui/hooks.dart:312:13)
#1155 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:399:5)
#1156 _drawFrame (dart:ui/hooks.dart:283:31)
main.dart
# main.dart
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
import 'package:go_router/go_router.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
final MapController mapController = MapController();
final router = GoRouter(
initialLocation: "/",
routes: [
GoRoute(path: "/", builder: (context, state) => const MyApp()),
GoRoute(
path: "/test",
builder: (context, state) => Container(
color: Colors.white,
child: Center(
child: TextButton(
onPressed: () => context.go("/"),
child: const Text("Go Home"),
),
),
),
),
],
);
void main() async {
await FMTCObjectBoxBackend().initialise(
rootDirectory: p.join((await getApplicationSupportDirectory()).absolute.path, "flutter_map_tile_cache"),
);
runApp(MaterialApp.router(
routerConfig: router,
));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: SizedBox.expand(
child: FlutterMap(
mapController: mapController,
children: [
TileLayer(
urlTemplate: 'https://api.mapbox.com/styles/v1/mapbox/streets-v12/tiles/256/{z}/{x}/{y}',
userAgentPackageName: "com.V3ntus.test",
maxZoom: 22,
maxNativeZoom: 22,
tileProvider: const FMTCStore('mapStore').getTileProvider(
settings: FMTCTileProviderSettings(
cachedValidDuration: const Duration(days: 60),
errorHandler: (error) {
if (error.type == FMTCBrowsingErrorType.negativeFetchResponse) {
// do nothing - indicates cache miss and HTTP error
}
},
),
),
),
Center(
child: TextButton(
onPressed: () => context.go("/test"),
child: const Text("Navigate Away"),
),
)
],
),
),
);
}
}
pubspec.yaml
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.6
flutter_map: ^6.1.0
flutter_map_tile_caching: ^9.0.0-dev.8
path: ^1.9.0
path_provider: ^2.1.2
go_router: ^13.2.2
dependency_overrides:
flutter_map:
git:
url: https://github.com/fleaflet/flutter_map.git
ref: 0fef8d6d36a735132b1b6cbe4624265beb4740bf
This can apparently be reproduced by providing a
UniqueKeyto theFlutterMap, then rebuilding.
Just curious if anyone has tried this to reproduce, and, if it had the same effect as for me.
If you need to insert your controller into some state management, this is the way I do it:
-
Define the map controller on the widget with the map, outside of the
buildmethod. i.e. it's only accessible to that widget and map. -
Attach the controller to the map as normal.
-
Use the
onMapReadycallback, and set the controller to whichever state you use. -
Be careful not to use it when the widget is built, or define the destroy method on the widget and set the state controlled controller to
null
If you're not trying to do state management and/or this doesn't work, can you explain what you're trying to do?
In my case, I'm trying to control the map outside of FlutterMap, thus attempting to define the controller outside of the widget class
Ok, so my suggestion above should work. That's what I needed to do as well.
Just wanted to confirm that the method JaffaKetchup suggested worked. This was my implementation:
- Define
MapControllerin your map widget and pass it to theFlutterMapwidget. - Define a nullable
MapControllervariable somewhere globally accessible. Ex.GlobalHandler.mapController MapOptions.onMapReadycallback assigns the map controller toGlobalHandler.mapController- In my
FlutterMapparent widget's overloadeddispose()where you callMapController.dispose(), I assign null toGlobalHandler.mapControllerjust to ensure I'm not using a disposed controller.
I'm going to close this for now. I think some careful consideration is required when hooking the controller up to state, but as the above suggestion seems to work fine (and that's part of the purpose of the onMapReady callback), I think this is all good.
Not sure what the fix would be for my case.
Here is the entirety of how I use MapController:
@override
Widget build(BuildContext context) {
final mapState = Provider.of<MapState>(context);
FlutterMap(
mapController: mapState.map,
And in mapState file:
class MapState extends ChangeNotifier {
final MapController _mapController = MapController();
LatLng _centerPosition = const LatLng(35, -100);
double zoomLevel = 7;
double minZoom = 4;
double maxZoom = 12;
double _imgScale = 1.8;
MapController get map => _mapController;
LatLng get center => _centerPosition;
double get zoom => zoomLevel;
double get imgScale => _imgScale;
}
Wasn't exactly sure how to implement the fix since I'm using provider. Thanks!
This was the same situation I was in.
Follow the guide above. Initialise the MapController directly in the widget around the map, not in the state provider. Use this controller directly in the map. Then use the onMapReady callback to add the controller into state at that point only.
Also consider implementing better disposal using the widget lifecycle method if you find yourself inadvertantly using it after disposal.
+ final mapController = MapController();
@override
Widget build(BuildContext context) {
- final mapState = Provider.of<MapState>(context);
FlutterMap(
- mapController: mapState.map,
+ mapController: mapController,
+ options: MapOptions(
+ onMapReady: () {
+ context.read<MapState>().map = mapController; // Can't remember if that's exactly correct or not
+ },
+ ),
class MapState extends ChangeNotifier {
- final MapController _mapController = MapController();
+ MapController? _mapController;
LatLng _centerPosition = const LatLng(35, -100);
double zoomLevel = 7;
double minZoom = 4;
double maxZoom = 12;
double _imgScale = 1.8;
- MapController get map => _mapController;
+ MapController get map => _mapController ?? (throw StateError('Not yet attached to map'));
+ set map(MapController newController) { // Consider also accepting null to implement disposal
+ _mapController = newController;
+ }
LatLng get center => _centerPosition;
double get zoom => zoomLevel;
double get imgScale => _imgScale;
}
I've updated the documentation which should help! https://docs.fleaflet.dev/v/v7-beta/usage/programmatic-interaction/external-custom-controllers#usage-within-a-state-system-model