使用期货波动喜欢按钮功能

时间:2018-08-07 06:26:58

标签: dart flutter flutter-layout dart-async

我正在尝试构建一个保存按钮,该按钮可让用户保存/取消保存ListView中显示的项目。

到目前为止我所拥有的:

  • 提供Future<bool>的存储库,用于确定图标应在哪个状态呈现
  • FutureBuilder,调用存储库并将图标呈现为已保存/未保存。
  • Icon包裹在GestureDetector中,当调用setState时,它会在onTap调用内调用存储库。

`

@override
Widget build(BuildContext context) {
  return FutureBuilder(
      future: _repository.isSaved(item),
      builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
          case ConnectionState.none:
          case ConnectionState.active:
            return Icon(Icons.favorite_border);
          case ConnectionState.done:
            return GestureDetector(
              child: Icon(
                  snapshot.data ? Icons.favorite : Icons.favorite_border,
                  color: snapshot.data ? Colors.red : null),
              onTap: () {
                setState(() {
                  if (snapshot.data) {
                    _repository.removeItem(item);
                  } else {
                    _repository.saveItem(item);
                  }
                });
              },
            );
        }
      });
}

`

我遇到的问题是,当我点击以将项目保存在列表中时-该项目已保存但是直到我将其滚动到屏幕之外然后再次打开时,图标才更新。 当我点击以取消保存项目时,其状态会立即反映出来并按预期更新。

我怀疑保存调用比删除调用花费的时间更长。这两个都是async操作:

void removeItem(String item) async {
    _databaseClient.deleteItem(item);
}

void saveItem(String item) async {
  _databaseClient.saveItem(item);
}

@override
void deleteItem(String item) async {
  var client = await db;
  client.delete("items_table", where: "item = '$item'"); // returns Future<int> but I'm not using this currently
}

void _saveItem(String item) async {
  var client = await db;
  client.insert("items_table", item); // returns Future<int> but I'm not using this currently
}

Future<bool> isSaved(String name) async {
    var matching = await _databaseClient.getNameByName(name);

    return matching != null && matching.isNotEmpty;
}

有什么想法会导致这种情况吗?

1 个答案:

答案 0 :(得分:2)

点击按钮时,将调用setState。然后FutureBuilder将等待isSaved方法。如果保存方法正在进行中。 isSaved将返回上一个状态,图标不会更改。

我建议等待Save and Remove方法的结果,然后再调用setState。

@override
Widget build(BuildContext context) {
  return FutureBuilder(
      future: _repository.isSaved(item),
      builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
          case ConnectionState.none:
          case ConnectionState.active:
            return Icon(Icons.favorite_border);
          case ConnectionState.done:
            return GestureDetector(
              child: Icon(
                  snapshot.data ? Icons.favorite : Icons.favorite_border,
                  color: snapshot.data ? Colors.red : null),
              onTap: () async{
                if (snapshot.data) {
                    await _repository.removeItem(item);
                  } else {
                    await _repository.saveItem(item);
                  }
                setState(() {

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

但是,如果方法花费的时间太长,则会延迟,从而导致不良的用户体验。最好在运行方法期间将图标更改为进度圈。