我有一个开关,可以改变数据库中的一个值。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);
}
},
);
}
你可以在init状态下获取数据,这样当你调用setState时就不会再被调用。
创建一个变量来检查数据是否到达,现在在init状态下调用_getValue。
bool isDataloaded = false;
bool currentValue = false;
现在在初始状态下调用_getValue。
@override
void initState() {
super.initState();
_getValue(widget.optionName).then((snapshot) {
setState(() {
currentValue = snapshot;
isDataloaded = true;
});
});
}
现在建立widget
return Container(
child: isDataloaded ? Switch(
value: currentValue,
onChanged: (bool newVal) {
setState(
() {
currentValue = newVal;
_changeValue(widget.optionName, newVal);
},
);
},
): Switch(value: currentValue, onChanged: null)
);