简体   繁体   中英

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. 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. 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. 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"

This indicates that only 7 selects were needed, but 20 were requested.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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