在 FutureBuilder() 而不是 initState() 中初始化 Sqflite 数据库访问

Posted

技术标签:

【中文标题】在 FutureBuilder() 而不是 initState() 中初始化 Sqflite 数据库访问【英文标题】:Initializing Sqflite database access in FutureBuilder() instead of initState() 【发布时间】:2022-01-22 22:39:50 【问题描述】:

试图弄清楚如何访问我的 Sqflite 实例并显示 ListView.builder 中的数据被包装到 FutureBuilder 中。以前我在调用initState 访问数据库,然后通过ListView.builder 显示数据。

下面一切正常:

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

@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
    ),
  );


以下是我将ListView.builder 放入FutureBuilder 后的内容。我也尝试按照此处的说明进行操作:Usage of FutureBuilder with setState

一切都坏了,我只能听到“糟糕!”:

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

  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
    ),
  );


Word.dart

class Word 
  late int? id;
  late String word1, meaning;

  Word();

  Word.map(dynamic obj)
    id = obj['ID'];
    word1 = obj['word1'];
    meaning = obj['meaning'];
  

  Map<String, dynamic>? toMap()
    var map = <String, dynamic>;
    map['word1'] = word1;
    map['meaning'] = 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();
  
...

【问题讨论】:

【参考方案1】:

不要在未来设定你的状态。 FutureBuilder 期望您的 Future 返回一个通过构建器部分中的快照公开的值。

看那个文档:https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

可以看到传递给 FutureBuilder 的 Future 并没有设置任何状态,而是返回了一个值。

FutureBuilder 的所有强大功能都来自于它能够使用 Future 并使用 Future 返回的数据或缺少的数据来渲染小部件的子树。

Future<List<Word>> getList() async 
    await DatabaseHelper.instance.database;
    return dbHelper.getAllWords();
  

Widget _buildSuggestions() 
    return FutureBuilder<List<Word>>(
      future: getList,
      builder: (BuildContext context, AsyncSnapshot<List<Word>>   snapshot) 
        if (snapshot.hasData) 
          // do stuff with the data in the snapshot
         else 
          // could display a spinner
        

【讨论】:

是的,谢谢,我改了,现在FutureBuilder通过Future获取数据。我试图以这个答案为指导,但仍然感到迷茫。 ***.com/questions/52021205/… 我已经编辑了我的答案让你开始 我猜在我的代码中是关于 Word.map 在这个阶段对 FutureBuilder 不完全满意的东西。

以上是关于在 FutureBuilder() 而不是 initState() 中初始化 Sqflite 数据库访问的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 使用 FutureBuilder 检索列表中的数据

Flutter futureBuilder 正在渲染未知的褪色卡片

使用 StreamBuilder 而不是 FeatureBuilder 来避免 Firestore 中的 whereIn 10 限制

在 FutureBuilder 的情况下,我应该如何获得一组可滚动的小部件而不会溢出

FutureBuilder 错误:返回类型“对象?”不是闭包上下文所要求的“小部件”

FutureBuilder : 方法 '&' 在 null 上被调用