dart /扑翼+火焰:如何在离线设置中获取添加的对象ID?

nbnkbykc  于 2023-04-09  发布在  其他
关注(0)|答案(1)|浏览(87)

我有一个表格来创建一个新的联系人,其中还包括一个“创建”按钮。当点击这个按钮,我希望表单进入只读模式,并在创建成功后,我想重定向到与新联系人相关的页面。
进入readonly可以正常工作,但是我在离线设置中遇到了重定向的问题。下面的createButton代码可以在在线设置中工作,其中createButton位于一个包含状态“pending”的有状态小部件中:

setState(() {
  pending = true;
});
FirebaseFirestore.instance.collection(...).withConverter(...).add(contact).then((addedContact) {
  setState(() {
    pending = false;
  });
  context.goNamed('contact', params: {'contactId' : addedContact.id});
});

但是在脱机设置中,有关相关集合的侦听器都将使用新联系人进行更新,但此回调永远不会解析。
我目前考虑手动生成一个id,监听集合,并在创建具有该id的对象时重定向,但对于这种情况有什么最佳实践吗?
可能相关:我将其作为Web应用程序进行测试,并在初始化时执行以下调用:

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform,
);
await FirebaseFirestore.instance.enablePersistence(const PersistenceSettings(synchronizeTabs: true));
await FirebaseFirestore.instance.disableNetwork();
yr9zkbsy

yr9zkbsy1#

您所描述的是预期的行为。then侦听器仅在文档写入服务器后才会被调用,而当您离线时不会发生这种情况。
完整行为如下所示:

  • 如果对add的调用本身完成,则写入操作被提交到本地缓存,并且如果/当连接可用时,将与服务器同步。
  • 如果对add的调用本身引发异常,则本地写操作失败并被中止(这种情况很少见)。
  • 如果then块被调用,则数据被写入服务器。
  • 如果Future被拒绝(并且catch块被执行),则数据在服务器上被拒绝-通常是因为您的安全规则,但请检查您得到的错误以确定原因。

也可以在这里看到我的答案:Firestore setDoc -响应未定义
因此,当前代码只在数据写入服务器后才调用setState。如果你想在数据写入本地缓存后运行它,你不应该使用then块,而是直接在add调用后运行代码:

setState(() {
  pending = true;
});
FirebaseFirestore.instance.collection(...).withConverter(...).add(contact);
setState(() {
  pending = false;
});
context.goNamed('contact', params: {'contactId' : addedContact.id});

这意味着状态会很短暂地挂起,因为本地写入会很快完成。我经常瞄准一个类似于WhatsApp的UI来显示状态,例如当数据在本地写入时显示一个复选标记,当数据也被提交到服务器时显示一个双复选标记。
最后,要在离线设置中获取文档的ID,请查看添加文档的文档中第三个代码示例中的以下代码:

// Add a new document with a generated id.
final data = <String, dynamic>{};

final newCityRef = db.collection("cities").doc();

// Later...
newCityRef.set(data);

您对add(...)的调用在此处分为两个:

  • doc(),它生成新的唯一ID,是一个纯客户端操作,也可以脱机工作。
  • set(...),它实际上写入数据。

因此,在上面的代码中,您可以从newCityRef.id获取新的ID。

相关问题