简体   繁体   English

颤动:如何防止Future快照不必要地发射

[英]Flutter: How can I prevent Future for snapshot from firing unnecessarily

I'm working on a program that displays a list from an SQFlite table. 我正在开发一个显示SQFlite表中列表的程序。 The future for the snapshot list is being fired for no reason that I can determine. 我无法确定快照列表的未来。 It fires approximately 3 times more than is needed. 它发射的火焰大约是所需的3倍。 The only times that it needs to fire are (1) the first time that program activates, and (2) when it returns from the update screen which can create, read, update, and delete. 它需要触发的唯一时间是(1)程序第一次激活,以及(2)何时从可以创建,读取,更新和删除的更新屏幕返回。 Consequently, I set a flag on return from that screen to indicate that the snapshot needs to be refreshed. 因此,我从该屏幕返回时设置一个标志,表示需要刷新快照。 Then in the function that selects the data, I check if the flag is set, and only then do I select the table. 然后在选择数据的函数中,检查是否设置了标志,然后才选择表。

Just running the program now for some additions and deletions resulted in the following for the select for the snapshot: 现在只需运行程序进行一些添加和删除,就可以选择快照:

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

This indicates that only 7 selects were needed, but 20 were requested. 这表明只需要7个选择,但要求20个。

Can someone advise me the correct way to prevent the Future firing when not necessary? 有人可以告诉我在没有必要时阻止未来射击的正确方法吗? Relevant code is below: 相关代码如下:

     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()}");
    }
  }

After some research, I believe that the answer to this question is that the selection of data from a database or elsewhere should be separate from the rebuild. 经过一些研究,我认为这个问题的答案是从数据库或其他地方选择数据应该与重建分开。 The rebuild is given this data as part of the rebuild, but it is not selected as part of the rebuild. 重建将作为重建的一部分提供此数据,但不会将其作为重建的一部分进行选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM