【问题标题】:Flutter: How can I prevent Future for snapshot from firing unnecessarilyFlutter:如何防止 Future 不必要地触发快照
【发布时间】:2019-03-22 13:25:20
【问题描述】:

我正在开发一个显示 SQFlite 表中的列表的程序。快照列表的未来正在被解雇,我无法确定。它的发射次数大约是需要的 3 倍。它需要触发的唯一时间是 (1) 程序第一次激活时,以及 (2) 从可以创建、读取、更新和删除的更新屏幕返回时。因此,我在从该屏幕返回时设置了一个标志,以指示需要刷新快照。然后在选择数据的函数中,检查是否设置了标志,然后才选择表。

现在只是运行程序进行一些添加和删除,导致快照选择如下:

“I/flutter (24769):Fetched = false,Fetch 尝试 = 20,Fetched = 7”

这表示只需要 7 个选择,但请求了 20 个。

有人可以告诉我在不必要时防止 Future 触发的正确方法吗? 相关代码如下:

     body: Container(
            padding: EdgeInsets.all(16.0),
            child: FutureBuilder<List<Map>>(
                future: _fetchDataFromDb(),
                builder: (context, AsyncSnapshot<List<Map>> snapshot) {
                    if (snapshot.connectionState == ConnectionState.done) {
                      if (!snapshot.hasError && snapshot.hasData) {
                        return ListView.builder(
                          itemCount:  snapshot == null ? 0 : snapshot.data.length,
                          itemBuilder: (context, index) {
                            return Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: <Widget>[
                                  ListTile(
                                      leading: (IconButton /* Edit */ (
                                          color: Colors.blue,
                                          icon: Icon(Icons.edit),
                                          onPressed: () => _showEditScreen(
                                              Crud.eUpdate,
                                              snapshot.data[index]))),
                                      title:
                                          Text(snapshot.data[index]['title']),
                                      subtitle:
                                          Text(snapshot.data[index]['detail']),
                                      onLongPress: () => _showEditScreen(
                                          Crud.eRead, snapshot.data[index]),
                                      trailing: (IconButton(
                                          color: Colors.red,
                                          icon: Icon(Icons.delete),
                                          onPressed: () => _showEditScreen(
                                              Crud.eDelete,
                                              snapshot.data[index])))),
                                ]);
                          });
                    }
                  }
                })),
  Future<List<Map>> _fetchDataFromDb() async {
    bool tfFetched = false;
    _iFetchAttempts++;
    if (_tfGetData) {
      print("Fetching data");
      _snapshot = await _dbHelper.getNoteRecs();
      tfFetched = true;
      _tfGetData = false;
      _iFetched++;
      setState(() => _iCount = _snapshot.length);
    }
    print(
        "Fetched = $tfFetched, Fetch attempts = $_iFetchAttempts, Fetched = $_iFetched");
    return _snapshot;
  }

  void _showEditScreen(Crud eCrud, data) async {
    try {
      NoteRec noteRec = data == null
          ? null
          : NoteRec(data['id'], data['title'], data['detail']);
      await Navigator.push(
          context,
          MaterialPageRoute(
              builder: (BuildContext context) =>
                  NoteEntry(g_crud: eCrud, g_noteRec: noteRec)));
      _tfGetData = true;   // SET FLAG TO INDICATE SELECT IS REQUIRED
    } catch (error) {
      print("Error on navigation = ${error.toString()}");
    }
  }

【问题讨论】:

  • 你为什么在这里这样做?:setState(() =&gt; _iCount = _snapshot.length); 调用setState 可能是导致你的FutureBuilder 多次构建的原因,因此再次调用_fetchDataFromDb。您的 _fetchDataFromDb 应该只做一件事,返回数据,在您的 FutureBuilder 中使用此方法时不更改状态。
  • 我需要 setState 来显示项目计数,如果没有它,它会显示不正确的计数。我之前已经删除了它,但我确实想要它,而且我不知道有其他方法可以在小部件中获得正确的计数。我再次将其删除并运行它,Future 仍然存在不必要的触发。即:“I/flutter (28461):Fetched = true,Fetch 尝试 = 21,Fetched = 11”

标签: flutter future


【解决方案1】:

经过一番研究,我相信这个问题的答案是从数据库或其他地方选择数据应该与重建分开。在重建过程中会为重建提供此数据,但不会将其选为重建的一部分。

【讨论】:

    猜你喜欢
    • 2021-03-02
    • 2021-09-19
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多