我是flutter的新手,我正试图使用ProxyProvider根据List返回List这是main.dart 中的代码
providers: [
FutureProvider<List<Mixer>>(
create: (_) => mixerdbService.retrieveMixers(),
initialData: <Mixer>[]),
ProxyProvider<List<Mixer>, List<int>>(update: (_, mixers, __) {
final List<int> ints = [];
for (var mixer in mixers) {
shipmentdbService
.retrieveNumberOfShipmentsByMixerId(mixer.id)
.then((value) => ints.add(value));
}
return ints;
}),
该方法按混合器ID 检索发货数量
Future<int> retrieveNumberOfShipmentsByMixerId(String? mixerId) async {
QuerySnapshot<Map<String, dynamic>> snapshot = await _db
.collection("shipments")
.where("mixer_id", isEqualTo: mixerId)
.get();
return snapshot.docs.length;
}
提供程序值是一个空列表。我认为代理提供者的更新方法中的逻辑存在错误。如果问题不清楚,请询问我有关的更多详细信息
解决方案
步骤#1
FutureProvider<List<Mixer>>(
create: (_) => mixerdbService.retrieveMixers(),
initialData: <Mixer>[]),
ProxyProvider<List<Mixer>, Future<List<int>>>(
update: (_, mixers, __) async {
final List<int> ints = [];
for (var mixer in mixers) {
final value = await shipmentdbService
.retrieveNumberOfShipmentsByMixerId(mixer.id);
ints.add(value);
}
return ints;
}),
步骤#2:使用FutureBuilder从提供程序解析Future
FutureBuilder<List<int>>(
future: context.read<Future<List<int>>>(),
builder: (_, snapshot) {
if (snapshot.hasData &&
snapshot.data!.isNotEmpty &&
listOfMixers.isNotEmpty) {
return ListView.builder(
itemCount: listOfMixers.length,
itemBuilder: (_, index) {
return MixerCard(
mixer: listOfMixers[index],
numberOfShipments: snapshot.data![index]);
});
}
return Center(
child: CircularProgressIndicator(),
);
},
),
这个解决方案还可以,但我仍在寻找另一个不使用FutureBuilder的解决方案。
问题是ProxyProvider
返回了一个尚未填充的列表,因为使用.then
进行异步调用。
为了解决它,返回一个Future<List<int>>
,并使更新函数async
。它将如下所示:
ProxyProvider<List<Mixer>, Future<List<int>>>(
update: (_, mixers, __) async {
final List<int> ints = [];
for (var mixer in mixers) {
final value = await shipmentdbService
.retrieveNumberOfShipmentsByMixerId(mixer.id);
ints.add(value);
}
return ints;
}),
解决方案1
然后添加另一个类似的FutureProvider
:
FutureProvider<List<int>>(
create: (context) => context.read<Future<List<int>>>(),
initialData: [],
),
这样就很容易像一样使用
final listOfMixers = context.watch<List<Mixer>>();
final listOfInts = context.watch<List<int>>();
return Scaffold(
body: listOfMixers.isNotEmpty && listOfInts.isNotEmpty // <- Here
? ListView.builder(
itemCount: listOfMixers.length,
itemBuilder: (context, index) {
return MixerCard(
mixer: listOfMixers[index],
numberOfShipments: listOfInts[index],
);
})
: const Center(
child: CircularProgressIndicator(),
),
);
解决方案2
或者使用FutureBuilder
从Future
中取出List<int>
。类似以下内容:
FutureBuilder<List<int>>(
future: context.read<Future<List<int>>>(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return ErrorPage();
}
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
}
final listLengths = snapshot.data;
// Do something with `listLengths`
}),