Home > Blockchain >  Flutter, setState() not working properly in Release but in Debug
Flutter, setState() not working properly in Release but in Debug

Time:05-17

I have a Stack which gets build inside of a FutureBuilder, part of the Stack is a ElevatedButton which is focusing to my current location on the map, which is also part of the Stack.

My idea is, that when i tap on a Marker of my map a boolean is being set to false (onMarkerTap), so the button disappears, and when i tap back on the map (onTap) the button appears again. I do this by using the setState() Method.

The problem is, all of this code is working without any problems when using the debug mode, but as soon as i use the release mode, the button disappears and never comes back.

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

  @override
  State<MapComponent> createState() => MapSampleState();
}

class MapSampleState extends State<MapComponent> {


  ...

  bool _focusLocationVisible = true;

  @override
  void initState() {
    // TODO: implement initState

    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }


  void setFocusButton(bool state){
    setState(() {
      _focusLocationVisible = state;
    });
  }

  @override
  Widget build(BuildContext context) {

    return FutureBuilder(
      
        future: _getDataFuture, 
        builder: (BuildContext jsoncontext, AsyncSnapshot snapshot) {
          if (!snapshot.hasData) {
            return (const Center(child: CircularProgressIndicator()));
          } else {
            ... 
          }

          var size = MediaQuery.of(context).size;

          return Stack(
            children: [
              FlutterMap(
                mapController: mapController,
                layers: [
                  TileLayerOptions(...),
                  LocationMarkerLayerOptions(),
                  MarkerClusterLayerOptions(

                    ...

                    onMarkerTap:(Marker marker)=>{

                      setFocusButton(false)

                    },

                    popupOptions: PopupOptions(
                        popupController: _popupController,
                        popupSnap: PopupSnap.mapBottom,
                        popupAnimation: PopupAnimation.fade(
                            duration: Duration(milliseconds: 200)),
                        popupBuilder: (_, marker) {
                          
                          return DraggableScrollableSheet(...);
                        }),
                  ),
                ],




                options: MapOptions(
                  onTap: (TapPosition, LatLang) =>
                      {
                        _popupController.hideAllPopups(),
                        setFocusButton(true),
                        },

                  ...

                  plugins: [
                    MarkerClusterPlugin(),
                    LocationMarkerPlugin(
                      //centerOnLocationUpdate: _centerOnLocationUpdate,
                      centerCurrentLocationStream: _centerCurrentLocationStreamController.stream,
                      centerAnimationDuration: Duration(milliseconds: 500),
                    )
                  ],
                ),

              ),
             if(_focusLocationVisible == true)  
              Positioned(
                right:  20,
                bottom: 40,

                //right:  _buttonrightPosition,
                //bottom: _buttonbottomPosition,
                  child: AnimatedOpacity(
                    opacity: _focusLocationVisible ? 1.0 : 0.0,
                    duration: const Duration(milliseconds: 500),
                    child: FloatingActionButton(
                          backgroundColor: Theme.of(context).bottomAppBarColor,
                          heroTag: null,
                          onPressed: () async {
                            // Location location = Location();
                            // LocationData curloc = await location.getLocation();
                            _centerCurrentLocationStreamController.add(16);
                            //mapController.move(LatLng(curloc.latitude!, curloc.longitude!),16);
                          },
                          child: const Icon(
                            Icons.my_location,
                            color: Colors.white,
                          ),
                        ),
                      
                  ),
              ),

            ],
          );
        });
  }
}


I already tried to call the setState Method directly inside of the onTaps, or by just moving the button simply out of site, or by setting another boolean with the value of the boolean outside of the build method at the beggining of the build method, but nothing worked.

Thank you in advance for your answers.

CodePudding user response:

i'm also new to flutter but when i faced similar situation i wraped the widget with ValueListenableBuilder and set the bool value as ValueNotifier. and it worked for me.

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

  @override
  State<MapComponent> createState() => MapSampleState();
}

class MapSampleState extends State<MapComponent> {


  ...

  @override
  void initState() {
    // TODO: implement initState

    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }


  @override
  Widget build(BuildContext context) {
    
    ValueNotifier<bool> _focusLocationVisible = ValueNotifier(true);

    return FutureBuilder(
      
        future: _getDataFuture, 
        builder: (BuildContext jsoncontext, AsyncSnapshot snapshot) {
          if (!snapshot.hasData) {
            return (const Center(child: CircularProgressIndicator()));
          } else {
            ... 
          }

          var size = MediaQuery.of(context).size;

          return ValueListenableBuilder(
                              valueListenable: _focusLocationVisible,
                              builder: (context, _value, _) {return Stack(
            children: [
              FlutterMap(
                mapController: mapController,
                layers: [
                  TileLayerOptions(...),
                  LocationMarkerLayerOptions(),
                  MarkerClusterLayerOptions(

                    ...

                    onMarkerTap:(Marker marker)=>{

                      _focusLocationVisible.value = false

                    },

                    popupOptions: PopupOptions(
                        popupController: _popupController,
                        popupSnap: PopupSnap.mapBottom,
                        popupAnimation: PopupAnimation.fade(
                            duration: Duration(milliseconds: 200)),
                        popupBuilder: (_, marker) {
                          
                          return DraggableScrollableSheet(...);
                        }),
                  ),
                ],




                options: MapOptions(
                  onTap: (TapPosition, LatLang) =>
                      {
                        _popupController.hideAllPopups(),
                        _focusLocationVisible.value = false,
                        },

                  ...

                  plugins: [
                    MarkerClusterPlugin(),
                    LocationMarkerPlugin(
                      //centerOnLocationUpdate: _centerOnLocationUpdate,
                      centerCurrentLocationStream: _centerCurrentLocationStreamController.stream,
                      centerAnimationDuration: Duration(milliseconds: 500),
                    )
                  ],
                ),

              ),
             if(_focusLocationVisible == true)  
              Positioned(
                right:  20,
                bottom: 40,

                //right:  _buttonrightPosition,
                //bottom: _buttonbottomPosition,
                  child: AnimatedOpacity(
                    opacity: _focusLocationVisible ? 1.0 : 0.0,
                    duration: const Duration(milliseconds: 500),
                    child: FloatingActionButton(
                          backgroundColor: Theme.of(context).bottomAppBarColor,
                          heroTag: null,
                          onPressed: () async {
                            // Location location = Location();
                            // LocationData curloc = await location.getLocation();
                            _centerCurrentLocationStreamController.add(16);
                            //mapController.move(LatLng(curloc.latitude!, curloc.longitude!),16);
                          },
                          child: const Icon(
                            Icons.my_location,
                            color: Colors.white,
                          ),
                        ),
                      
                  ),
              ),

            ],
          );});
        });
  }
}

Hope this works for you too.

CodePudding user response:

Be careful, the setState could reload the Futurebuilder. As recommanded, use composition widget aggressively. ValueNotifier is good for a small project but for a big project your code would be hard to understand.

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


  @override
  Widget build(BuildContext context) {
    return FutureBuilder(

        future: _getDataFuture,
        builder: (BuildContext jsoncontext, AsyncSnapshot snapshot) {
          if (snapshot.connectionState = ConnectionState.waiting) {
            return (const Center(child: CircularProgressIndicator()));
          } else if (!snapshot.hasData) {
            return Text("No data");
          }


          final data = snapshot.data;

          var size = MediaQuery
              .of(context)
              .size;

          return BuildStack(yourData: data);
        });
  }

}


class BuildStack extends StatefulWidget {
  final dynamic yourData;

  const BuildStack({Key? key, required this.yourData}) : super(key: key);

  @override
  _BuildStackState createState() => _BuildStackState();
}

class _BuildStackState extends State<BuildStack> {

  late bool _focusLocationVisible = true;

  @override
  void initState() {
    super.initState();
    _focusLocationVisible = true;
  }


  void setFocusButton() {
    setState(() {
      _focusLocationVisible = !_focusLocationVisible;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        FlutterMap(
          mapController: mapController,
          layers: [
            TileLayerOptions(...),
            LocationMarkerLayerOptions(),
            MarkerClusterLayerOptions(


              onMarkerTap: (Marker marker) =>
                  setFocusButton()
              ,

              popupOptions: PopupOptions(
                  popupController: _popupController,
                  popupSnap: PopupSnap.mapBottom,
                  popupAnimation: PopupAnimation.fade(
                      duration: const Duration(milliseconds: 200)),
                  popupBuilder: (_, marker) {
                    return DraggableScrollableSheet(...);
                  }),
            ),
          ],


          options: MapOptions(
            onTap: (TapPosition, LatLang) =>
            {
              _popupController.hideAllPopups(),
              setFocusButton(),
            },


            plugins: [
              MarkerClusterPlugin(),
              LocationMarkerPlugin(
                //centerOnLocationUpdate: _centerOnLocationUpdate,
                centerCurrentLocationStream: _centerCurrentLocationStreamController
                    .stream,
                centerAnimationDuration: const Duration(
                    milliseconds: 500),
              )
            ],
          ),

        ),
        if(_focusLocationVisible)
          Positioned(
            right: 20,
            bottom: 40,

            //right:  _buttonrightPosition,
            //bottom: _buttonbottomPosition,
            child: AnimatedOpacity(
              opacity: _focusLocationVisible ? 1.0 : 0.0,
              duration: const Duration(milliseconds: 500),
              child: FloatingActionButton(
                backgroundColor: Theme
                    .of(context)
                    .bottomAppBarColor,
                heroTag: null,
                onPressed: () async {
                  // Location location = Location();
                  // LocationData curloc = await location.getLocation();
                  _centerCurrentLocationStreamController.add(16);
                  //mapController.move(LatLng(curloc.latitude!, curloc.longitude!),16);
                },
                child: const Icon(
                  Icons.my_location,
                  color: Colors.white,
                ),
              ),

            )
            ,
          )
        ,

      ]
      ,
    );
  }
}

  • Related