我使用ListView.builder
来管理一长串小部件,每个小部件都有一个进度条。
我已经查看了其他答案,并确保由ListView.builder
构造的每个Widget
都有自己的状态。在我的例子中,ConversionGroupWidget
管理自己的状态。
问题是更新来自Stream
。当监听流更新时,如果需要,我会创建一个新的小部件,然后setState()
刷新整个列表。但是,如果更新只是一个进度更改,我如何从ListView
中选择需要setState()
调用的单个项目?下面是带有TODO
注解的行。
class ProgressView extends StatefulWidget {
final Stream<ProgressStatus> statusStream;
const ProgressView({super.key, required this.statusStream});
@override
State<ProgressView> createState() => _ProgressViewState();
}
class _ProgressViewState extends State<ProgressView> {
final ProgressData conversionProgress = ProgressData();
@override
Widget build(BuildContext context) {
widget.statusStream.listen((update) async {
final group = conversionProgress.groupToUpdate(update);
if (group == null) {
await conversionProgress.addConversionGroup(update);
setState(() {});
} else {
// TODO!
}
});
return ListView.builder(
itemCount: conversionProgress.conversionGroups.length,
itemBuilder: (context, idx) {
var group = conversionProgress.conversionGroups[idx];
return Container(
padding: Style.prefsPaneSideInsets,
child: Column(children: [
Style.prefsPaneSectionVSpacer,
ConversionGroupWidget(
groupStatus: group,
)
]));
});
}
}
1条答案
按热度按时间ycggw6v21#
问题是,让单个
Widget
成为无状态的,从根本上说与Stream
不兼容。Stream
事件更新Widget
s,因此根据定义,如果Widget
是无状态的,则无法更新。这导致了一个大的全局状态,并调用setState()
来立即更新所有内容。我通过使用有状态的小部件并让每个
Widget
在其构造函数中接受一个经过过滤的Stream
来解决这个问题。然后在initState
中,状态在widget.stream
上调用listen()
并以这种方式更新自己。