StreamBuilder 会在无状态小部件中自动关闭流吗?

Posted

技术标签:

【中文标题】StreamBuilder 会在无状态小部件中自动关闭流吗?【英文标题】:Will StreamBuilder auto off the stream in stateless widget? 【发布时间】:2019-06-23 11:40:33 【问题描述】:

当我在 Flutter 中使用 BLOC 时,例如:

class StreamText extends StatelessWidget 
  StreamText(
    this.stream, 
    this.style,
  );

  final Stream<dynamic> stream;
  final TextStyle style;

  @override
  Widget build(BuildContext context) 
    return StreamBuilder<dynamic>(
      stream: stream,
      builder: (context, snapshot) 
        return Text(snapshot.data.toString(), style: style);
      ,
    );
  

这是一个无状态小部件,没有dispose() 方法;

当这个小部件被破坏时,我怎么能关闭流,或者它会自动关闭流?

【问题讨论】:

"off the stream"?你是什​​么意思? StreamController.close()? @pskink 是的。那是 【参考方案1】:

不,它不会关闭Stream,但会关闭用于构建小部件的StreamSubscription

如果Stream 不用于其他任何用途,最好以某种方式处置Stream(通过将其包装在StatefulWidget 上或使用BlocProvider 方法)。

如果您在其他地方使用Stream,或者您将来将使用Stream,则无需担心在StreamBuilder 上使用它会导致内存泄漏。只要您在其他人停止使用它时丢弃它。

StreamBuilder 本身扩展自 StreamBuilderBase,这是一个 StatefulWidget,它使用自己的 dispose 方法处理 StreamSubscription

这是来自async.dart 库的摘录。

/// State for [StreamBuilderBase].
class _StreamBuilderBaseState<T, S> extends State<StreamBuilderBase<T, S>> 
  StreamSubscription<T> _subscription;

  @override
  void initState() 
    //...
    _subscribe();
  

  @override
  void dispose() 
    _unsubscribe();
    super.dispose();
  

  void _subscribe() 
    if (widget.stream != null) 
      _subscription = widget.stream.listen((T data) 
    //...
    
  

  void _unsubscribe() 
    if (_subscription != null) 
      _subscription.cancel();
      _subscription = null;
    
  

如你所见,StreamSubscriptioninitState上初始化,在dispose状态调用上自动取消,所以这里使用的订阅会一直关闭,你不用担心它。

【讨论】:

【参考方案2】:

不,它不会自动关闭。通常,流的所有者是管理流状态的人。

我认为一个好的解决方案是让有状态小部件拥有您的 BLoC,并在其 dispose 方法中关闭流。

This article 显示了一种可能的实现方式,请查看BlocProvider 类。

【讨论】:

【参考方案3】:

在无状态小部件中,当小部件从小部件树中移除时,StreamBuilder 本身将“自动关闭”。您无需处理任何事情。

但是,如果您有一个发送快照的 StreamController,您应该在完成后手动关闭它。

【讨论】:

【参考方案4】:

您正在将流传递到无状态小部件,您应该关闭流,覆盖与您拥有流实例的有状态小部件关联的子类 State 类的 dispose 方法。此外,在此小部件中,您必须检查 snapshot.data 是否为 null(并返回例如 Container()),否则您会收到错误,因为您没有将 initialData 传递给StreamBuilder.

【讨论】:

"overriding the dispose method" - 在StatefulWidget? dispose()State的方法 对不起,你是对的,我的意思是与 Statuful 小部件关联的 State 的子类。 我怎样才能关闭来自 Observable 内部流构建器或无状态小部件的流?我知道如何关闭 BehaviorSubject 的流

以上是关于StreamBuilder 会在无状态小部件中自动关闭流吗?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 在无状态小部件中动态地将项目添加到 ListView

在 StreamBuilder 中使用 Selector (Provider) 时不必要的小部件重建

Streambuilder 渲染两次,第一次使用初始数据,第二次使用正确数据,但小部件不更新

无状态颤振小部件中的非最终字段

如何为 StreamBuilder 生成的小部件设置动画?

在 StreamBuilder 中使用 SnackBar 的奇特方式是啥?