当FutureBuilder中的属性更改时,如何使开关正确地“动画”?

时间:2020-04-30 15:51:18

标签: firebase flutter google-cloud-firestore

我有一个可以更改数据库值的开关。 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);
        }
      },
    );
  }

1 个答案:

答案 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)
 );