Flutter,setState() 在 Release 中无法正常工作,但在 Debug 中无法正常工作
Flutter, setState() not working properly in Release but in Debug
我有一个在 FutureBuilder 中构建的 Stack,Stack 的一部分是一个 ElevatedButton,它聚焦于我在地图上的当前位置,它也是 Stack 的一部分。
我的想法是,当我点击地图上的标记时,布尔值被设置为 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,
),
),
),
),
],
);
});
}
}
我已经尝试直接在 onTaps 内部调用 setState 方法,或者只是将按钮简单地移出站点,或者在开始时在构建方法之外设置另一个布尔值构建方法,但没有任何效果。
提前感谢您的回答。
我也是 flutter 的新手,但是当我遇到类似情况时,我用 ValueListenableBuilder 包装了小部件并将 bool 值设置为 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,
),
),
)
,
)
,
]
,
);
}
}
我有一个在 FutureBuilder 中构建的 Stack,Stack 的一部分是一个 ElevatedButton,它聚焦于我在地图上的当前位置,它也是 Stack 的一部分。
我的想法是,当我点击地图上的标记时,布尔值被设置为 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,
),
),
),
),
],
);
});
}
}
我已经尝试直接在 onTaps 内部调用 setState 方法,或者只是将按钮简单地移出站点,或者在开始时在构建方法之外设置另一个布尔值构建方法,但没有任何效果。
提前感谢您的回答。
我也是 flutter 的新手,但是当我遇到类似情况时,我用 ValueListenableBuilder 包装了小部件并将 bool 值设置为 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,
),
),
)
,
)
,
]
,
);
}
}