【问题标题】:Cloud Firestore not updating correctly when record is added in Flutter在 Flutter 中添加记录时,Cloud Firestore 未正确更新
【发布时间】:2018-02-02 19:02:17
【问题描述】:

我正在开发一个 Flutter 应用程序,我正在使用 cloud_firestore 插件。我有一个提交的集合,我正在使用StreamBuilder 来显示它们(我假设它会在流更改时更新)。我从插件示例中直接拿了这个例子,因为没有太多关于如何使用插件做事的文档。当我添加一条记录时,我显示的文档列表变长了,但它似乎是在复制其中一个提交,而不是插入新的提交。新提交的内容添加后不显示。这是我如何显示列表的代码:

// At the top of the class home.dart. 
final submissions = Firestore.instance.collection('submissions');

// This is in submission-list.dart and the above submissions 
// is passed in to the contructor
Widget build(BuildContext context) {
    return new StreamBuilder<QuerySnapshot>(
      stream: submissions
          .where('owner_uid', isEqualTo: this.user.uid)
          .orderBy('timestamp', descending: true)
          .snapshots,
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (!snapshot.hasData) return new Text('Loading...');
        return new ListView(
          children: snapshot.data.documents.map((DocumentSnapshot document) {
            var date = _formatDate(document['timestamp']);
            String body = _constructCardBody(document['weight'],
                bodyFat: document['bodyFat']);
            String id = document.documentID;
            return new SubmissionCard(id: id, title: date, body: body, submissions: submissions);
          }).toList(),
        );
      },
    );
  }

这是submission-card.dart的完整内容:

import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

import '../utils/logger.dart';
import './block-button.dart';

class SubmissionCard extends StatefulWidget {
  final String id;
  final String title;
  final String body;
  final CollectionReference submissions;

  SubmissionCard({this.id, this.title, this.body, this.submissions});

  @override
  State<StatefulWidget> createState() =>
      new _SubmissionCardState(id: this.id, title: this.title, body: this.body, submissions: this.submissions);
}

class _SubmissionCardState extends State<SubmissionCard> {
  final String id;
  final String title;
  final String body;
  bool showActionButtons = false;
  final CollectionReference submissions;

  _SubmissionCardState({this.id, this.title, this.body, this.submissions});

  void _showEditScreen() {}

  void _showActionButtons() {
    setState(() {
      showActionButtons = true;
    });
  }

  void _hideActionButtons() {
    setState(() {
      showActionButtons = false;
    });
  }

  Future<Null> _deleteSubmission() async {
    try {
      await submissions.document(id).delete();
      await Logger.log('error', 'stackTrace');
    } catch (error, stackTrace) {
      await Logger.log(error, stackTrace);
    }
  }

  void _closeDialog() {
    Navigator.of(context).pop();
    _hideActionButtons();
  }

  Future<Null> _warnAboutDeletion() async {
    return showDialog(
        context: context,
        child: new SimpleDialog(
          title: new Text('Are you sure?'),
          children: <Widget>[
            new SimpleDialogOption(
              onPressed: () {
                this._deleteSubmission();
                this._closeDialog();
              },
              child: new Text("I'm sure. Delete it."),
            ),
            new SimpleDialogOption(
              onPressed: _closeDialog,
              child: new Text("Nope. Take me back."),
            ),
          ],
        )
    );
  }

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onLongPress: _showActionButtons,
      onTap: _hideActionButtons,
      child: new Card(
        elevation: showActionButtons ? 8.0 : 2.0,
        key: new GlobalKey(),
        child: new Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            new ListTile(
              trailing: showActionButtons
                  ? new Row(
                      children: <Widget>[
                        new IconButton(
                          padding: const EdgeInsets.all(0.0),
                          icon: const Icon(Icons.edit),
                          onPressed: _showEditScreen,
                          color: Colors.black12,
                          splashColor: Colors.black26,
                          highlightColor: Colors.black12,
                        ),
                        new IconButton(
                          padding: const EdgeInsets.all(0.0),
                          icon: const Icon(Icons.delete),
                          onPressed: _warnAboutDeletion,
                          color: Colors.redAccent,
                          splashColor: Colors.black26,
                          highlightColor: Colors.black12,
                        ),
                      ],
                    )
                  : new Container(),
              isThreeLine: true,
              title: new Text(title),
              subtitle: new Text(
                body,
                style: new TextStyle(height: 3.0),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

回购链接:https://github.com/dericgw/bodwatch

以前,当我使用 Firebase 时,这个集合会自动更新。我以前从未见过这种奇怪的行为。现在,我是 Flutter 和 Dart 的新手,所以我肯定会遗漏一些东西。

【问题讨论】:

  • _submissions 是什么?和home.dart中的submissions一样吗?
  • 您也能描述一下“我正在显示的文档列表变长了,但它似乎是在复制其中一个提交而不是插入新提交。新提交后没有显示被添加。”更准确?
  • @Pacane 是的,_submissions 与 submissions 相同。澄清一下,我所说的 - 如果列表有 3 个项目并且我添加了一个项目,那么列表就有 4 个项目。但是,添加到列表中的项目不是提交的项目。原来的 3 个项目之一被复制。有意义吗?
  • 如果没有完整的代码,很难看到真正发生了什么。能贴出SubmissionCard的代码吗?另外,您确定它没有添加新项目,但您只是没有正确显示这些项目吗?因为流的第一个快照应该是所有记录,随后的快照将只是更改。
  • 我可能没有正确显示它们,因为我是 Flutter(和 Dart)的新手。过去使用 Firebase,(使用 JS)快照更改时,事情会自动更新。我不需要做任何事情来手动更新它。我已更新答案以显示提交卡代码和回购链接。

标签: firebase dart flutter


【解决方案1】:

您需要在 firebase 控制台中添加索引。

在您的情况下,您需要多个索引。 1.owner_uid,升序 2. 时间戳,降序

问题应该解决了。

【讨论】:

    猜你喜欢
    • 2022-12-04
    • 2015-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 2020-05-05
    • 2011-07-19
    • 2020-12-04
    相关资源
    最近更新 更多