我的代码有问题。
从本质上讲,我试图做的是在从sqflite数据库中提取数据后,动态创建显示文件信息的卡。
我遇到的问题是,我的ListView
的返回类型为<List<Widget>>
,而来自sqfliteDB的查询返回的是<Future<List<Widget>>>
。我知道这个问题需要FutureBuilder
,但我不确定在哪里实现它
这是错误消息:
参数类型Future<列表<小工具>gt;无法分配给参数类型列表<小工具>
这是从DB中提取数据的代码,并将生成的卡小部件存储在列表itemsList
中
Future<List<Widget>> getRecordedItems() async {
List<Widget> itemsList = [];
final dbHelper helper = dbHelper();
var recordings = await helper.getRecordings();
var len = recordings.length;
for (var i = 0; i < len; i++) {
var id = recordings[i]["id"];
var filepath = recordings[i]["filepath"];
var filelength = recordings[i]["length"];
var loopCode = Card1(filepath, i, len, filelength);
itemsList.add(loopCode);
}
return itemsList;
}
这是我当前的return
声明:
var items = getRecordedItems();
return ListView(children: items);
这是在另一个文件中接收ListView
对象的代码:
Widget build(BuildContext context) {
final AudioPlayerController audioController =
Provider.of<AudioPlayerController>(context);
return Scaffold(
backgroundColor: AppColor.AppBackgroundColor,
appBar: const PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight), child: Titlebar()),
body: Container(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(children: [
const PastRecordingsHeader(name: "$name"),
const Spacer(
flex: 1,
),
SizedBox(
height: MediaQuery.of(context).size.height /1.67,
child: RecordingCard(name: '$name')
)
]),
)),
bottomNavigationBar: PrevRecordingsNavBar();
CCD_ 8是调用CCD_ 9的地方。
有人能帮我了解FutureBuilder的位置吗?
尝试在ListView
外部和ListView
内部实现FutureBuilder
,但均无效。
要正确获取数据,您需要将一个(FutureBuilder)Widget放在您已经拥有的(ListView)Widget之上,在这种情况下,在数据到来之前,列表不会实现,因此为了检查数据是否到来,您需要如下图所示制作(if语句)来显示其他Widget,直到数据到来,在函数完成后,您的列表将显示从函数中提取的数据。
FutureBuilder<List<Widget>>(
future: getRecordedItems(),
builder: (context, data) {
if (data.hasData) {
List<Widget> dataList = data.data!;
return ListView(children: dataList);
} else {
Text(
'There is no data'); // put any widget you want in case there is no data
}
}),
您必须返回FutureBuilder
,而不是返回ListView
,因此
Future<List<Widget>> items = [];
@override
void initState() {
items = getRecordedItems(); // future is created just once, here!
super.initState();
}
...
// somewhere further down in your build method:
return FutureBuilder<List<Widget>>(
future: items, // do not create the future here!
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
List<Widget> items = snapshot.data ?? [];
return ListView(children: items);
} else { // if not yet done, return a progress indicator!
return CircularProgressIndicator();
}
}),
请特别注意不要在future:
参数中创建future
,否则每次重建小部件时都会创建它!
有关更多信息,请参阅FutureBuilder 上精彩的本周小工具章节