通过 FutureBuilder 访问 Sqflite 数据的 Flutter 问题。 ConnectionState.done, 空

Flutter problem with access to Sqflite data via FutureBuilder. ConnectionState.done, null

正在尝试更改对数据库的访问权限:

只是初始化对数据的访问 initState,然后在 ListView.builder

中显示结果

ListView.builder里面的FutureBuilder.

但是我在这个 FutureBuilder 中迷路了,我的列表是空的。我猜我的问题出在 updateAndGetList() 里面。 在控制台中我得到这个:

flutter: AsyncSnapshot<List<Word>>(ConnectionState.done, null, , #0      _RandomWordsState.updateAndGetList.<anonymous closure> (package:myapplesson/main.dart:115:7)

有人可以帮助或推动我朝着正确的方向前进吗?

这是我的main.dart

DatabaseHelper dbHelper = DatabaseHelper.instance;
final _suggestions = <Word>[];

  @override
  void initState() {
    super.initState();
    // initial load
    _listFuture = updateAndGetList();
  }

  late Future<List<Word>> _listFuture;

  void refreshList() {
    // reload
    setState(() {
      _listFuture = updateAndGetList();
    });
  }

//I GUESS I AM DOING SOMETHING WRONG HERE!?

  Future<List<Word>> updateAndGetList() async {
    await DatabaseHelper.instance.database;
    // return the list here
    return dbHelper.getAllWords().then((rows) {
      setState(() {
        rows?.forEach((row) { _suggestions.add(Word.map(row));});
      });
      throw '';
    });
  }

  Widget _buildSuggestions() {
    return FutureBuilder<List<Word>>(
      future: _listFuture,
      builder: (BuildContext context, AsyncSnapshot<List<Word>> snapshot) {
        if (snapshot.hasData) {
          return ListView.builder(
            itemCount: _suggestions.length,
            itemBuilder: (context, i) {
              if (i.isOdd) return const Divider();
              final index = i ~/ 2;
              if (index >= _suggestions.length) {
                _suggestions.addAll(_suggestions.take(10));
              }
              return _buildRow(_suggestions[index]);
            });
        }else if (snapshot.hasError) {
          return Text("Oops!");
        }
        return Center(child: CircularProgressIndicator());
      },
    );
  }

Widget _buildRow(Word pair) {
  return ListTile(
    title: Text(
      pair.word1
    ),
    subtitle: Text(
        pair.meaning
    ),
  );
}

在完成更改之前,一切都是这样工作的:

//perfectly worked

@override
void initState() {
  super.initState();
  dbHelper.getAllWords().then((rows) {
    setState(() {
      rows?.forEach((row) { _suggestions.add(Word.map(row));});
    });
  });
}

Widget _buildSuggestions() {
  return ListView.builder(
      itemCount: _suggestions.length,
      itemBuilder: (context, i) {
        if (i.isOdd) return const Divider();
        final index = i ~/ 2;
        if (index >= _suggestions.length) {
          _suggestions.addAll(_suggestions.take(10));
        }
        return _buildRow(_suggestions[index]);
      });
}
Widget _buildRow(Word pair) {
  return ListTile(
    title: Text(
      pair.word1
    ),
    subtitle: Text(
        pair.meaning
    ),
  );
}

这是我的Database_helper.dart

...
Future<List<Map<String, dynamic>>?> getAllWords() async {
    Database? db = await instance.database;
    var result = await db?.query(table);
    return result?.toList();
  }
...

在您的 updateAndGetList 函数中,您应该 return 一个 Future<List<Word>>。相反,您不 return 任何东西(而是设置状态)。考虑将其调整为如下所示:

  Future<List<Word>> updateAndGetList() async {
    await DatabaseHelper.instance.database;
    // return the list here
    return dbHelper.getAllWords().then((rows) {
      // build the list of words and then return it!
      List<Word> res = [];
      for (var row in rows) {
        res.add(Word.map(row));;      
      }
      return res;
    });
  }

您现在可以在未来的构建器中从您的快照访问此单词列表

return FutureBuilder<List<Word>>(
      future: _listFuture,
      builder: (BuildContext context, AsyncSnapshot<List<Word>> snapshot) {
        if (snapshot.hasData) {
          
          // the word list as retrieved from your future
          List<Word> wordList = snapshot.data;
          return ListView.builder(
            itemCount: wordList.length,
            itemBuilder: (context, i) {
              if (i.isOdd) return const Divider();
              final index = i ~/ 2;
              if (index >= wordList.length) {
                wordList.addAll(wordList.take(10));
              }
              // use the word listto build your rows
              return _buildRow(wordList[index]);
            });
        }else if (snapshot.hasError) {
          return Text("Oops!");
        }
        return Center(child: CircularProgressIndicator());
      },
    );

无需为您的建议保留单独的变量。

此外,您实际上并不需要 _listFuture 变量,除非您在其他地方需要它。在您的 FutureBuilder 中,您可以简单地使用

return FutureBuilder<List<Word>>(
  future: updateAndGetList(),
  builder: ...
);