【问题标题】:Flutter Firestore not giving updated data when I add a field to a document from the console当我从控制台向文档添加字段时,Flutter Firestore 未提供更新的数据
【发布时间】:2021-12-04 08:15:16
【问题描述】:

我在 Flutter Firestore 2.5.3 中遇到了一个奇怪的错误,如果我向 Firebase 控制台中的文档添加新字段 (customer_type),应用程序无法检索新添加的字段并引发异常:

CastError (type 'Null' is not a subtype of type 'String' in type cast)

但它不为空。我使用 Firebase 控制台中的值添加了新字段。它在文档中。原来 Firebase 正在获取旧文档数据没有新添加的字段。

我正在使用来自 Riverpod 的 StreamProvider。代码如下:

static Stream<Customer?> _watchCustomer(final ProviderRefBase ref) async* {
  final auth = await ref.watch(authProvider.last);
  if (auth == null) {
    yield null;
  } else {
    final customerRef = _db.collection('customers').toCustomerRef(auth.uid);
    await for (var customer in customerRef.snapshots().map((doc) => doc.data())) yield customer;
  }
}

可能出了什么问题?

编辑:

所有名称、集合和字段都是正确的,它们的类型也是正确的。如果我重新安装应用程序或完全清除应用程序存储,相同的确切代码将正常工作。但是,如果我只是清除缓存,它就不起作用。它在调试时阻碍了我的工作流程,我想知道为什么会这样。如需更多参考,这是我的“客户”模型:

Customer.fromMap(final String documentID, final Map<String, dynamic> map)
  : id = documentID,
    name = map['customer_name'] as String,
    mobile = map['customer_mobile'] as String,
    type = map['customer_type'] as String;

它设置为不可为空,因为我正在建立一个严格的架构。但这不应该是一个问题,因为它在数据库中不是空的。我已将customer_type 添加到集合中的所有文档中。而且它们都没有将值设置为 null。

这只能意味着我从 Firestore 获得的地图找不到必要的密钥。这意味着我仍在从 Firestore 获取旧数据(没有新字段)。是什么赋予了?至少当我清除缓存时,它应该会给我更新的数据。

【问题讨论】:

  • 您的集合“客户”在您的 FB 控制台中的名称/拼写是否完全相同?
  • 另外可能是数据快照本身有问题,能否提供完整的错误信息?
  • @JahnE。这就是完整的错误。它基本上中途停止应用程序并向我显示调试消息。是的,“客户”是完全相同的集合名称 - 拼写正确。它以前工作得很好。当我添加新字段时它就停止工作了。

标签: firebase flutter google-cloud-firestore stream riverpod


【解决方案1】:

因为在您在Firestore 控制台中添加新字段之前,您的代码可以正常工作,这意味着问题出在您的新字段上

问题是您在Firestore 中添加了一个与您的模型(客户类)拼写不同(区分大小写或拼写错误)的字段,或者type 不合适(例如,您尝试从a 中读取int String,或者您尝试从map 中读取array 等)

如果这没有帮助,请告诉我?

【讨论】:

  • 绝对不是这样。没有错字。我已经检查了三次。如果类型错误,它会告诉我,例如'int' is not a subtype of 'String' in type cast。该错误明确指出null,这意味着他无法检测到它。而且,最重要的是,如果我重新安装该应用程序,它就可以正常工作。
  • @Adifyr 您可能拼写正确。但是,您写的其余部分根本不是真的。 Null 是一种类型,就像 int 一样。您的代码检测到 null(由于某种原因,例如您的 Stream 没有正确收听) - 要了解转换错误,请阅读 dart 团队的这篇短文:dart.dev/null-safety/understanding-null-safety
  • @JahnE。这是真的,我确实理解零安全性。我的模型中的字符串设置为不可为空。这是有意设计的,因为新字段已通过脚本添加到我收藏的所有文档中。我基本上是在建立一个严格的模式。它是后端和我的应用程序中的字符串。看看我编辑的问题,当我清除存储时,一切正常。如果我犯了一个铸造错误,情况就不是这样了。
  • 明白。很奇怪的bug。当您发现问题时,很想知道是什么问题。祝你好运 ;0)
【解决方案2】:

到目前为止,我所知道的是,在从服务器获取更新版本之前,该流会返回文档的即时本地快照。这是有道理的;除了如果我清除缓存,那么它应该直接转到服务器并且不会给我任何错误 - 这不会发生。

我认为 Firestore 可能会将本地快照存储在更多地方,而不仅仅是缓存,但这只是我的猜测。

目前,我已通过在构造函数中进行简单的 null 检查来解决此问题:

type = map['customer_type'] as String? ?? 'customer'

但是,此修复尚无定论,我不会将此标记为答案,因为我觉得应该对正在发生的事情进行适当的解释。

【讨论】:

  • 您是否测试过在您的应用程序中将持久性设置为 false?根据这个related question,在这种情况下擦除缓存可能无法正常工作,因为它会自行重建。 Disabling persistencepersistenceEnabled 设置可能适用于从 Firestore 获取最新文档。
  • 从技术上讲,是的,完全禁用持久性很可能会解决问题。问题是,我想在应用程序中保持持久性。禁用它似乎很像试图用大锤杀死一只苍蝇。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2020-09-26
  • 2020-09-12
  • 2021-09-08
相关资源
最近更新 更多