假设定义了两个列表:

List<MediaItem?> playlist = [];    
List<Item> items = [Item(data:'vasya')];

两个模型:

class MediaItem {
  final String id;
  
  MediaItem({
    required this.id
  });
}

class Item {
  final String data;
  
  Item({
    required this.data,
  });
  
  MediaItem toMediaItem() => MediaItem(
    id: data,
  );
}

然后按如下方式填充第一个列表:

playlist = items.map(
  (el) => el.toMediaItem()
).toList();

然后,如果我try 改变列表中的元素:

playlist[0] = null;

IDE/DartPad认为没有问题,但在运行后,Dart抛出错误:Uncaught Error: TypeError: null: type 'JSNull' is not a subtype of type 'MediaItem' 仅当添加空安全问号toMediaItem()方法时才起作用:

MediaItem? toMediaItem() => MediaItem(
  id: data,
);

怎么说呢?我认为定义一个List<MediaItem?>应该足以在任何时候将value更改为null.

DartPad示例:https://dartpad.dev/?id=592167a9f6e1a08344a51800c67887d3

推荐答案

原因是您最终在这里创建了一个新的List对象:

playlist = items.map(
  (el) => el.toMediaItem()
).toList();

是的,DART知道您的变量的类型,但在本例中,它采用返回值map()的类型,并使用该类型来确定创建的列表的类型.在本例中,您最终得到了一个List<MediaItem>对象,它可以毫无问题地分配给一个List<MediaItem?>变量.

如果您改用已创建的playlist个列表:

playlist.addAll(items.map((el) => el.toMediaItem()));

那么你就不会受到这个问题的打击.或者,您还可以告诉DART您希望map()返回的确切类型:

playlist = items.map<MediaItem?>((el) => el.toMediaItem()).toList();

EDIT:

您还可以执行以下操作:

playlist = [for (final el in items) el.toMediaItem()];

其中,DART将查看变量的类型,并使用该类型来确定应为哪种类型创建列表.

Flutter相关问答推荐

Flutter—如何在Riverpod中使用全类状态?

我有相关的下拉菜单Flutter Windows应用程序的问题

如何在Ffltter 3.16中设置标准的提升按钮主题?

按一下按钮即可更新 fl_chart

如何在 Flutter 中设计像 zomato 应用程序一样的搜索字段?

Flutter 需要 Xcode 14 或更高版本

ScaffoldMessenger 在等待键下方不起作用

TextField 中的富文本并获取 RenderParagraph

为 flutter app/firebase 保存 chatgpt api-key 的正确方法是什么

Flutter中pubspec.yaml文件中的name参数是什么?

Flutter屏幕适配 - 在模拟器和真实手机上文本尺寸不同

#Flutter/Riverpod - 使用 AsyncNotifier 时是否可以仅调用错误?

如何与 PostgreSQL 和外部网站交互 flutter apk?

SfCircularChart 周围的额外间距

Flutter - 使用 pin 进行身份验证

Firestore:缓存和读取数据

我几乎每次都将 Stateless Widget 与 BLoC 一起使用.我错了吗?

Flutter:如何将列表转换为字符串?

Android Studio 模拟器屏幕闪烁

在 Flutter 中更新对象实例属性的最佳实践是什么?该实例嵌套在提供程序类的映射中,如下所示