问题

我目前正在学习Flutter,熟悉TS.虽然Flutter/Dart以强类型而闻名,但我在试图缩小可空类型(这在TS中是可能的)时遇到了困难.

具体地说,我使用了FutureBuilder和一个Rocc函数来获取数据,并try 基于这些数据构建小部件.为了简洁起见,数据是List<{ path: String, ... }>.但是,我无法访问snapshot.data:

问题

我的方法看起来很蠢.我查了一下文档,我找到的最接近的解决方案是type promotion,但我相信这不是我想要的.

代码

child: FutureBuilder(
    future: _selectedImages,
    builder: (context, snapshot) {
        // error: dart(unchecked_use_of_nullable_value)
        if (snapshot.hasData) {
            log(snapshot.data[0].path);
        }

        // error: dart(unchecked_use_of_nullable_value)
        if (snapshot.hasData && snapshot.data.isNotEmpty) {
            log(snapshot.data[0].path);
        }

        // this works
        if (snapshot.hasData) {
            final tmp = snapshot.data?[0].path;
            if (tmp != null) {
                log(tmp);
            }
        }
    },
),

编辑@ pskink

我相信我涵盖了所有的 case ,为什么错误仍然弹出,你知道为什么吗?

pskink

                // this works
                // builder: ((context, snapshot) =>
                //     switch ((snapshot.connectionState, snapshot.data)) {
                //       // TODO: Handle this case.
                //       (ConnectionState.none, _) =>
                //         Text('null ${snapshot.data.toString()}'),
                //       (ConnectionState.waiting, _) => const Text('text'),
                //       (ConnectionState.active, _) => const Text('text'),
                //       (ConnectionState.done, null) => const Text('text'),
                //       (ConnectionState.done, final data?) => const Text('text'),
                //     }),

                builder: (context, snapshot) {
                  switch ((snapshot.connectionState, snapshot.data)) {
                    case (ConnectionState.none, _):
                      return Text('null ${snapshot.data.toString()}');
                    case (ConnectionState.waiting, _):
                      return const Text('text');
                    case (ConnectionState.active, _):
                      return const Text('text');
                    case (ConnectionState.done, null):
                      return const Text('text');
                    case (ConnectionState.done, final data?):
                      return const Text('text');
                    // no error if have this
                    // default:
                    //   return const Text('text');
                  }
                }

推荐答案

snapshot.hasData已经意味着snapshot.data != null.您可以查看async.dart文件的源代码:

启动获取hasData=>;日期!=空;

但不幸的是,Dart Analytic没有足够的智能来知道类中的参数不是空的.

Dart只能将局部变量提升为空安全. AsyncSnapshot对象的字段data理论上可以在下次读取时返回任何内容,因此不能基于判断在一个地方读取的值是否为null来升级它. 即使该数据是最终的,不能被设置,而是被提升,这意味着作者不能在future 改变该字段. 因此,提升仅适用于局部变量.

如果你想要一个快速的解决,你可以只是把!后面的数据后,你判断snapshot.hasData,它会很好:

if (snapshot.hasData) {
   final data = snapshot.data!;
   // from here data can use without null error
}

下面是我经常使用FutureBuilder的代码:

    FutureBuilder(
      future: _selectedImages,
      builder: (context, snapshot) {
        final data = snapshot.data;
        
        if (data == null) {
          return YourLoadingWidget();
        }

        // do whatever you want with non-nullable data here

      },
    )

Flutter相关问答推荐

Box约束强制无限高:SizedBox. Expand()

如何使一个悬浮的appbar在flutter?

无法将Flutter 连接到Firebase

如果文档确实存在,则FiRestore将";False";返回到";if-Document-Existes";...还是我说错了?

在Flutter 中每次点击按钮时都很难调用自定义函数

如何正确处理Flutter 翼中使用火基时发生的碰撞?

确保通过在CheckIfFavoriteMovieEvent((event,emit){...})上注册处理程序误差

来自FirebaseAuth的错误DisplayName和邮箱在Flutter应用程序中给出错误

框中的Flutter 适配图像

在 flutter 吧蜂巢中拯救主题

FittedBox叠加技术在Flutter 中的应用

'type' Icon '不是类型' IconData '的子类型

FutureProvider 不返回数据给 UI

如何在android中 Select 任何文件/文件路径 - Flutter

如何从底部导航栏打开 bottomModal 表?

Flutter ListView 在 Column 中工作但在 Row 中不工作

Flutter Websockets MacOS:相同的代码在调试模式下有效,但在发布模式下无效:(操作系统错误:提供了 node 名或服务名..)

.info/connected 这两个代码之间有什么区别吗?

如何在 flutter 中制作这种类型的扩展瓦片

使用 onPressed 切换到另一个屏幕无法正常工作