在 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 的情况下,我应该如何获得一组可滚动的小部件而不会溢出