Flutter StreamBuilder 与 initialData 和 null-awareness

Posted

技术标签:

【中文标题】Flutter StreamBuilder 与 initialData 和 null-awareness【英文标题】:Flutter StreamBuilder with initialData and null-awareness 【发布时间】:2021-06-24 16:39:44 【问题描述】:

我在理解使用新的 null 感知运算符的 StreamBuilder 时遇到了一些问题。

作为一个学习项目,我正在使用 BloC 模式实现登录流程。对于我的电子邮件登录表单,我创建了一个模型类,我可以通过 StreamBuilder 访问它。如果不使用 initialData,snapshot.data 可以为空是完全有意义的。但是,将 initialData 设置为预定义的空模型,snapshot.data 永远不会为空,对吧?这是我的代码 sn-p:

 @override
  Widget build(BuildContext context) 
    return StreamBuilder<EmailSignInModel>(
        stream: widget.bloc.modelStream,
        initialData: EmailSignInModel(),
        builder: (context, snapshot) 
          final EmailSignInModel model = snapshot.data;
          return Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              mainAxisSize: MainAxisSize.min,
              children: _buildChildren(),
            ),
          );
        );
  

编译器警告我 snapshot.data 是 类型,它不等于 .我可以用snapshot.data ?? EmailSignModel() 来解决这个问题,但这对于initialData 来说是多余的,对吧?

处理这种情况并处理 Dart 的 null 意识的正确方法是什么?

【问题讨论】:

只是想说这是一个非常有趣的问题。事实是 AsyncSnapshot 将有一个类型为 T? 的 getter 数据,因此可空性被纳入 AsyncSnapshot 类。也许这应该在 Flutter Github 中报告? github.com/flutter/flutter/issues 我去查看源代码,发现他们对此有解决方案。下面回答了 【参考方案1】:

深入研究源代码,我发现了以下内容:

https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/widgets/async.dart

  /// The latest data received by the asynchronous computation.
  ///
  /// If this is non-null, [hasData] will be true.
  ///
  /// If [error] is not null, this will be null. See [hasError].
  ///
  /// If the asynchronous computation has never returned a value, this may be
  /// set to an initial data value specified by the relevant widget. See
  /// [FutureBuilder.initialData] and [StreamBuilder.initialData].
  final T? data;

  /// Returns latest data received, failing if there is no data.
  ///
  /// Throws [error], if [hasError]. Throws [StateError], if neither [hasData]
  /// nor [hasError].
  T get requireData 
    if (hasData)
      return data!;
    if (hasError)
      throw error!;
    throw StateError('Snapshot has neither data nor error');
  

AsyncSnapshot 实际上有一个requireData getter,它将确保非空或会抛出错误。所以只需将snapshot.data 替换为snapshot.requireData

这仍然需要一些手动工作,其中initialDatarequireData 的使用需要保持同步。您也可以只使用snapshot.data!,它的作用基本相同。

【讨论】:

感谢您的明确答复。有趣的是,我距离显示部分答案的文档字符串只有一次 ctrl 单击。总而言之,使用 initialData 不能为空,使用 requireData 是一个很好的解决方案。我也喜欢简单的使用!直接,因为它总是接近于 initialData 参数并明确它不能为空。

以上是关于Flutter StreamBuilder 与 initialData 和 null-awareness的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:如何将 StreamBuilder 与 ListView.separated 一起使用

Flutter StreamBuilder 与 initialData 和 null-awareness

FirebaseStorage + Flutter,streamBuilder?

来自一个 StreamBuilder 的 Flutter 快照显示在另一个 StreamBuilder 中

Flutter:Streambuilder - 关闭流

Flutter:StreamBuilder 快照——无数据