我有一个可以更改数据库值的开关。 FutureBuilder的未来是获取开关的当前值(我这样做是为了如果该值无法更新,则开关仍将是正确的值)。切换开关时,我调用setState来更改开关的值和数据库中的值。这样做的副作用是每次使用该开关时都会重新构建该开关和FutureBuilder,从而导致该开关闪烁。
有没有一种方法可以在FutureBuilder中实现该开关,从而正确地执行“开关”动画?
这是我的开关小部件:
dynamic currentValue = false;
Future<void> _changeValue(String optionName, dynamic value) async {
await widget.db
.collection('CameraSettings')
.document(optionName)
.updateData({optionName: value});
}
Future<dynamic> _getValue(String optionName) async {
DocumentSnapshot value =
await widget.db.collection('CameraSettings').document(optionName).get();
return value.data[optionName];
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _getValue(widget.optionName),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
currentValue = snapshot.data;
return Switch(
value: currentValue,
onChanged: (bool newVal) {
setState(
() {
currentValue = newVal;
_changeValue(widget.optionName, newVal);
},
);
},
);
} else {
return Switch(value: currentValue, onChanged: null);
}
},
);
}
答案 0 :(得分:1)
您可以使数据处于init状态,因此在调用setState时不会再次调用它。
创建一个变量,以检查是否到达数据。
bool isDataloaded = false;
bool currentValue = false;
现在以初始状态调用_getValue。
@override
void initState() {
super.initState();
_getValue(widget.optionName).then((snapshot) {
setState(() {
currentValue = snapshot;
isDataloaded = true;
});
});
}
现在构建窗口小部件
return Container(
child: isDataloaded ? Switch(
value: currentValue,
onChanged: (bool newVal) {
setState(
() {
currentValue = newVal;
_changeValue(widget.optionName, newVal);
},
);
},
): Switch(value: currentValue, onChanged: null)
);