Flutter, setState() не работает должным образом в Release, но в Debug

У меня есть стек, который создается внутри FutureBuilder, частью стека является ElevatedButton, который фокусируется на моем текущем местоположении на карте, что также является частью стека.

Моя идея заключается в том, что когда я нажимаю на маркер моей карты, для логического значения устанавливается значение false (onMarkerTap), поэтому кнопка исчезает, а когда я снова нажимаю на карту (onTap), кнопка появляется снова. Я делаю это с помощью метода setState().

Проблема в том, что весь этот код работает без проблем при использовании режима отладки, но как только я использую режим выпуска, кнопка исчезает и больше не появляется.

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,
                          ),
                        ),
                      
                  ),
              ),

            ],
          );
        });
  }
}


Я уже пытался вызвать метод setState непосредственно внутри onTaps, или просто переместив кнопку просто за пределы сайта, или установив другое логическое значение со значением логического значения вне метода сборки в начале метода сборки, но ничего не работало.

Заранее спасибо за ваши ответы.

0
0
32
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

я также новичок в флаттере, но когда я столкнулся с подобной ситуацией, я обернул виджет с помощью ValueListenableBuilder и установил логическое значение как ValueNotifier. и это сработало для меня.

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,
                          ),
                        ),
                      
                  ),
              ),

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

Надеюсь, это сработает и для вас.

Будьте осторожны, setState может перезагрузить Futurebuilder. В соответствии с рекомендациями, используйте виджет композиции агрессивно. ValueNotifier хорош для небольшого проекта, но для большого проекта ваш код будет трудно понять.

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,
                ),
              ),

            )
            ,
          )
        ,

      ]
      ,
    );
  }
}

Другие вопросы по теме