我正在尝试使用StreamProvider
(来自this令人敬畏的软件包),但是我一直在努力使特定的流工作。
我创建了一个StreamController
,用于通过其Stream
将数据添加到其Sink
中。所有这些似乎都工作正常。但是,当将此Stream
与StreamProvider
一起使用时,小部件树不会反射(reflect)Stream
的更改。但是,使用StreamBuilder
确实可以正常工作。
使用StreamProvider
的代码:
class TestPage extends StatelessWidget {
final Mockup exchange = ExchangeApi.mockup;
@override
Widget build(BuildContext context) {
return StreamProvider<List<Data>>(
builder: (BuildContext context) => Wrapper.mockup.stream,
initialData: null,
catchError: (BuildContext context, e) {
print("Error: $e");
return null;
},
child: TestPageBody(),
);
}
}
class TestPageBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<Data> dataList = Provider.of<List<Data>>(context);
return ListView.builder(
itemCount: dataList?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
return Text(dataList[index].name);
},
);
}
}
我一直在寻找为什么这行不通,但是还没有找到答案。但是,我确实找到了一些东西:
任何帮助将不胜感激!
最佳答案
大多数提供程序(不包括ChangeNotifierProvider
)的默认行为是假定传递的值是不可变的。
因此,如果您的流发出的值与先前发出的值相同,则不会重建依赖项。
有两种解决方案:
previousValue == newValue
。 updateShouldNotify
,以便在不更改值的情况下不对其进行过滤。一个简单的
updateShouldNotify: (_, __) => true
就可以了。 在理想世界中,更喜欢不变性。
这可以通过在将对象发送到
streamController.add(value)
之前制作对象的副本来完成:List<T> value;
streamController.add(List.from(value));
第二个(可选)步骤是重写
updateShouldNotify
(或对象上的operator==
)以通知提供者该值没有更改。使用
List
,可以使用ListEquality
中的collection/collection.dart
来完成:import 'package:provider/provider.dart';
import 'package:collection/collection.dart';
StreamProvider<List<int>>(
builder: (_) => stream,
updateShouldNotify: const ListEquality<int>().equals,
);