tlserver / flutter_map_location_marker

A flutter map plugin for displaying device current location.
https://pub.dev/packages/flutter_map_location_marker
BSD 3-Clause "New" or "Revised" License
102 stars 93 forks source link

Crashes when used with BottomNavigationBar #61

Closed dfrobese closed 1 year ago

dfrobese commented 1 year ago
The following StateError was thrown building RawGestureDetector(state: RawGestureDetectorState#777e9(gestures: [tap, long press, vertical drag, horizontal drag, scale])):
Bad state: Stream has already been listened to.

The relevant error-causing widget was: 
  FlutterMap FlutterMap:file:///Users/dfrobese/StudioProjects/vfrinfo_flutter/lib/main_controller.dart:113:18
When the exception was thrown, this was the stack: 
#6      _CurrentLocationLayerState._subscriptPositionStream (package:flutter_map_location_marker/src/current_location_layer.dart:281:57)
#7      _CurrentLocationLayerState.initState (package:flutter_map_location_marker/src/current_location_layer.dart:157:5)
#8      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5101:55)
#9      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4944:5)
#10     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3953:16)
#11     MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6512:36)
#12     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6524:32)
...     Normal element mounting (7 frames)
#19     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3953:16)
#20     MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6512:36)
#21     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6524:32)
...     Normal element mounting (35 frames)
#56     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3953:16)
#57     Element.updateChild (package:flutter/src/widgets/framework.dart:3682:18)
#58     _LayoutBuilderElement._layout.layoutCallback (package:flutter/src/widgets/layout_builder.dart:135:18)
#59     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2682:19)
#60     _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:153:12)
#61     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2300:59)
#62     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1056:15)
#63     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2300:14)
#64     RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:228:7)
#65     _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:313:5)
#66     RenderObject.layout (package:flutter/src/rendering/object.dart:2189:7)
#67     RenderBox.layout (package:flutter/src/rendering/box.dart:2430:11)
#68     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:240:12)
#69     RenderObject.layout (package:flutter/src/rendering/object.dart:2189:7)
#70     RenderBox.layout (package:flutter/src/rendering/box.dart:2430:11)
#71     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:171:12)
#72     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1080:7)
#73     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:240:7)
#74     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:410:14)
#75     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2027:7)
#76     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1020:18)
#77     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:516:19)
#78     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:865:13)
#79     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:381:5)
#80     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1289:15)
#81     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1218:9)
#82     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1076:5)
#83     _invoke (dart:ui/hooks.dart:145:13)
#84     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:338:5)
#85     _drawFrame (dart:ui/hooks.dart:112:31)
(elided 6 frames from dart:async)
/// Map widget
  @override
  Widget build(BuildContext context) {
    developer.log("MainControllerPageState build");
    return Scaffold(
      appBar: AppBar(title: const Text('VFRInfo')),
      drawer: _drawer(context),
      body: _pages[currentPage],
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.map),
            label: 'map',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.connecting_airports),
            label: 'airports',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.route),
            label: 'route',
          ),
        ],
        onTap: ((index) {
          _followCurrentLocationStreamController.close();
          setState(() {
            currentPage = index;

          });
        }),
      ),
    );
  }

late final List<Widget> _pages = [
    _map(), // includes FlutterMap with location marker as child
    StationListPage(). // a list widget
  ];
tlserver commented 1 year ago

A non boardcast stream can only be subscribed once. I think this problem is caused by passing a subscripted stream into a CurrentLocationMarker. To solve this error, you can easily call .asBroadcastStream() before subscribing the stream. See also this example.

dfrobese commented 1 year ago

Thanks for help. With this modifications the crash doesn't come up again. But the location marker will not appear again, when I switch back to the map.

tlserver commented 1 year ago

Does the example mentioned before work on your device? If yes, you may try to modify the example to meet your need. If it does not work after modification, some code snippet is useful for giving help.