StreamProvider 不更新状态

Posted

技术标签:

【中文标题】StreamProvider 不更新状态【英文标题】:StreamProvider not updating state 【发布时间】:2019-12-13 08:49:24 【问题描述】:

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

我创建了一个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);
      ,
    );
  

我一直在寻找为什么这不起作用,但还没有找到答案。但这里有一些我确实发现的东西:

使用 Flutter Desktop Embedding,当窗口调整大小(从而强制重建)时,UI 确实反映了流中的更改。使用热刷新时会看到相同的效果。 流不断添加新数据,我通过调试测试了这一点并简单地打印出数据

任何帮助将不胜感激!

【问题讨论】:

如果你添加一个updateShouldNotify: (_, __) =&gt; true,这行得通吗? (这只是为了确认一些事情) 就是这样!再次感谢雷米……但是,你能澄清一下为什么这是必要的吗?我使用的其他流似乎从来没有必要(尽管这可能是巧合)。我认为该属性的用例类似于性能(限制重新渲染)。 【参考方案1】:

大多数提供者(不包括ChangeNotifierProvider)的默认行为是假定传递的值是不可变的。

因此,如果您的流发出的值与之前发出的相同,则不会重建依赖项。

有两种解决方案:

使您的流发出的值不可变,以便执行previousValue == newValue 正常工作。

覆盖 updateShouldNotify 以不过滤未更改的值。

一个简单的updateShouldNotify: (_, __) =&gt; true 就可以了。


在理想世界中,更喜欢不变性。

这可以通过在将对象发送到streamController.add(value) 之前制作一个副本来完成:

List<T> value;
streamController.add(List.from(value));

第二个(可选)步骤是覆盖updateShouldNotify(或您的对象上的operator==)以通知提供者该值没有改变。

对于List,这可以使用来自collection/collection.dartListEquality 来完成:

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

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

【讨论】:

这是有道理的,因为我添加到 List 并且实际上并没有创建新的 List 对象。感谢您的快速回复,感谢您提供的精美包裹!

以上是关于StreamProvider 不更新状态的主要内容,如果未能解决你的问题,请参考以下文章

StreamProvider 不更新列表

Flutter StreamProvider 没有将数据推送到 UI

如何根据riverpods streamProvider 更新嵌套屏幕?

当用户更改时,监听用户的 StreamProvider 不会更新

在 Flutter 中使用 StreamProvider 4.0.1 从 Firebase 监控身份验证状态

Flutter Provider,当他的参数改变时更新 StreamProvider