StreamProvider 不更新状态

StreamProvider not updating state

我正在尝试使用 StreamProvider(来自 this awesome package),但我一直在努力让特定的流工作。

我创建了一个 StreamController,我用它通过它的 Sink 向它的 Stream 添加数据。所有这一切似乎工作正常。但是当 StreamStreamProvider 一起使用时,小部件树不会反映 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,这可以使用 collection/collection.dart 中的 ListEquality 来完成:

import 'package:provider/provider.dart';
import 'package:collection/collection.dart';

StreamProvider<List<int>>(
  builder: (_) => stream,
  updateShouldNotify: const ListEquality<int>().equals,
);