添加数据而不是覆盖它

Posted

技术标签:

【中文标题】添加数据而不是覆盖它【英文标题】:Add data instead of overwriting it 【发布时间】:2021-06-30 15:48:59 【问题描述】:

当我使用弹出 AddPlanScreen 向小部件添加注释时,它会覆盖文档而不是添加它。注册、记录和设置数据正常工作。

我尝试做的事情:

    使用 FirebaseFirestore.instance.runTransaction,但在向地图添加数据时,我无法对字符串使用 + 运算符。 set(..., SetOptions(merge:true)) 更新方法 我是否必须尝试创建一个新地图并在那里添加数据?我是编程新手,如果有任何建议,我将不胜感激。

这是我用来设置和获取数据的方法


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

class MyProvider extends ChangeNotifier 
  Map<String, dynamic> _names = ;

  String name(String key) => _names[key];

  void setName(String key, String newString) 
    _names[key] = newString;
    var firebaseUser = FirebaseAuth.instance.currentUser;
    FirebaseFirestore.instance
        .collection('Notes')
        .doc(firebaseUser.uid)
        .set(_names);
  


  void fetchData() 
    var firebaseUser = FirebaseAuth.instance.currentUser;
    FirebaseFirestore.instance
        .collection('Notes')
        .doc(firebaseUser.uid)
        .get()
        .then((DocumentSnapshot documentSnapshot) 
      if (documentSnapshot.exists) 
        var data = documentSnapshot.data();
        _names = data;
       else 
        print('The document does not exist on the database');
      
    );
  


这是我显示所有笔记的规划器屏幕


import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:my_planner_app/widgets/my_provider.dart';
import 'file:///C:/Users/krisk/androidStudioProjects/planner_app/lib/widgets/weekday_card.dart';
import 'package:provider/provider.dart';

class PlannerScreen extends StatefulWidget 
  static const String id = 'planner_screen';

  @override
  _PlannerScreenState createState() => _PlannerScreenState();


class _PlannerScreenState extends State<PlannerScreen> 

  Widget build(BuildContext context) 
    Provider.of<MyProvider>(context, listen: false)
        .fetchData();
    var size = MediaQuery.of(context).size;

    final double itemHeight = (size.height - 24) / 2;
    final double itemWidth = size.width / 2;
    return Scaffold(
      backgroundColor: Color(0xFFcf9e9f),
      body: Container(
        child: GridView(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
            childAspectRatio: (itemWidth / itemHeight),
          ),
          children: <Widget>[
            WeekDayCard(
              text: '',
            ),
            WeekDayCard(text: 'Monday' ),
            WeekDayCard(text: 'Tuesday'),
            WeekDayCard(text: 'Wednesday'),
            WeekDayCard(text: 'Thursday'),
            WeekDayCard(text: 'Friday'),
            WeekDayCard(text: 'Saturday'),
            WeekDayCard(text: 'Sunday'),
            WeekDayCard(text: 'Notes'),
          ],
        ),
      ),
    );
  

这是关联的 WeekDayCard 小部件


import 'package:flutter/material.dart';
import 'package:my_planner_app/screens/addPlan_screen.dart';
import 'package:provider/provider.dart';
import 'package:my_planner_app/widgets/my_provider.dart';

class WeekDayCard extends StatefulWidget 
  WeekDayCard(@required this.text, this.name);
  final String name;
  final String text;

  @override
  _WeekDayCardState createState() => _WeekDayCardState();


class _WeekDayCardState extends State<WeekDayCard> 
  @override


  Widget build(BuildContext context) 
    return Consumer<MyProvider>(builder: (context, myProvider, child) 
      return Card(
        color: Color(0xFFFEEFCD),
        elevation: 10,
        child: Column(
          children: [
            Text(widget.text),
            Text(Provider.of<MyProvider>(context).name(widget.text) ?? ''
    ),
            Expanded(
              child: InkWell(
                onTap: () 
                  showModalBottomSheet(
                    backgroundColor: Color(0xFFFEEFCD),
                    context: context,
                    builder: (context) => AddPlanScreen(weekdayName: widget.text),
                  );
                ,
              ),
            ),
          ],
        ),
      );
    );
  


这是关联的 AddPlanScreen


import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_planner_app/widgets/my_provider.dart';

class AddPlanScreen extends StatefulWidget 
  final String weekdayName;
  const AddPlanScreen(Key key, this.weekdayName) : super(key: key);

  @override
  _AddPlanScreenState createState() => _AddPlanScreenState();


class _AddPlanScreenState extends State<AddPlanScreen> 
  String name;
  @override
  Widget build(BuildContext context) 
    return Column(
      children: [
        Expanded(
          child: TextFormField(
            onChanged: (text) 
              name = text;
            ,
            decoration: InputDecoration(
              border: InputBorder.none,
            ),
            minLines: 10,
            maxLines: 30,
            autocorrect: false,
          ),
        ),
        FlatButton(
          onPressed: () 
            Provider.of<MyProvider>(context, listen: false)
                .setName(widget.weekdayName, name);
            Navigator.pop(context);
          ,
          color: Colors.blue,
        ),
      ],
    );
  


【问题讨论】:

【参考方案1】:

只有当你是第一次创建一个文档并且你想给它一个指定的ID(不是由firebase随机生成的)时,你才应该使用set。或者,第二个用途是当您想故意改写现有数据时。

当你想更新一个文档或其中的单个值\条目时,你只需使用:collection('yourCollection').doc('yourDocID').update("nameOfnewField": "new data")

此更新方法不会覆盖您现有的文档,它只会添加一个名为"nameOfnewField" 的新字段,或者如果该字段已经存在,它只会覆盖它。

即,如果 nameOfnewFieldfalse 的值,当您更新它时,使用 .update("nameOfnewField": "true"),它会变为 true,但文档的其余部分不会更改。

【讨论】:

以上是关于添加数据而不是覆盖它的主要内容,如果未能解决你的问题,请参考以下文章

带有 Flutter 的实时数据库覆盖数据而不是将其添加到现有节点

将数据添加到现有 JSON 文件而不覆盖它

如何使用扩展运算符向对象添加属性,而不是覆盖它?

如何使用 Eclipse 启动将本机库添加到“java.library.path”(而不是覆盖它)

如何在 firebase 中添加来自用户的数据,而不是替换已经存在的数据?

如何在不覆盖现有记录的情况下将新行添加到数据表