首页 > 解决方案 > Flutter:解决执行 updateData 时出错,NOT_FOUND:没有要更新的文档

问题描述

当我尝试在我的 firebase 数据库中更新我的 userData 时出现以下错误

E/flutter ( 4756): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(Error performing updateData, NOT_FOUND: No document to update: projects/(DBname)/databases/(default)/documents/userData/ckua6TCjc2Dx76W6efuV, null)

这是我的 UserData 模型类

class UserData {
//  String userId;
  String id;
  String firstName;
  String lastName;
  String phoneNumber;
  String role;
  String streetAddress;
  String city;
  String state;
  String postcode;
  String country;
  Timestamp createdAt;
  Timestamp updatedAt;

  UserData();

  UserData.fromMap(Map<String, dynamic> data) {
    id = data['id'];
//    userId = data['user_id'];
    firstName = data['first_name'];
    lastName = data['last_name'];
    phoneNumber = data['phone_number'];
    role = data['role'];
    streetAddress = data['street_address'];
    city = data['city'];
    postcode = data['postcode'];
    state = data['state'];
    country = data['country'];
    createdAt = data['created_at'];
    updatedAt = data['updated_at'];
  }

  Map<String, dynamic> toMap() {
    return {
      'id': id,
//      'user_id': userId,
      'first_name': firstName,
      'last_name': lastName,
      'phone_number': phoneNumber,
      'role': role,
      'street_address': streetAddress,
      'city': city,
      'postcode': postcode,
      'state': state,
      'country': country,
      'created_at': createdAt,
      'updated_at': updatedAt,
    };
  }
}

这是我的 UserDataNotifier 类

class UserDataNotifier with ChangeNotifier {
  UserData _loggedInUserData;

  Query userDataCollection = Firestore.instance.collection('userData');

  UserData get loggedInUserData => _loggedInUserData;

  set loggedInUserData(UserData userData) {
    _loggedInUserData = userData;
    notifyListeners();
  }

  getUserData(UserDataNotifier userDataNotifier) async {
    await userDataCollection
        .orderBy('created_at', descending: true)
        .getDocuments();
    notifyListeners();
  }

  Future updateUserData(UserData userData, bool isUpdating) async {
    CollectionReference userDataRef =
        await Firestore.instance.collection('userData');

    if (isUpdating) {
      userData.updatedAt = Timestamp.now();
      await userDataRef.document(userData.id).updateData(userData.toMap());
      print('updated userdata with id: ${userData.id}');
    } else {
      userData.createdAt = Timestamp.now();

      DocumentReference documentReference =
          await userDataRef.add(userData.toMap());

      userData.id = documentReference.documentID;

      print('created userdata successfully with id: ${userData.id}');

      await documentReference.setData(userData.toMap(), merge: true);
    }
    notifyListeners();
  }
}

这是我的编辑个人资料屏幕,它调用我的 userNotifier

class ProfileFormScreen extends StatefulWidget {
  static const String id = 'profile_form';

  @override
  _ProfileFormScreenState createState() => _ProfileFormScreenState();
}

class _ProfileFormScreenState extends State<ProfileFormScreen> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  UserData _userData;

  //global declarations
  String selectedBusinessTypeDropDownValue = 'Fashion';
  String selectedCurrencyDropDownValue = 'NGN: Nigerian Naira';
  String selectedCountryDropDownValue = 'Nigeria';
  String email;

  _saveUserData(BuildContext context) {
    UserDataNotifier userNotifier =
        Provider.of<UserDataNotifier>(context, listen: false);

    if (!_formKey.currentState.validate()) {
      return;
    }
    _formKey.currentState.save();
    userNotifier.updateUserData(_userData, true);
    Navigator.pop(context);
  }

  @override
  void initState() {
    super.initState();

    UserDataNotifier userDataNotifier =
        Provider.of<UserDataNotifier>(context, listen: false);

    if (userDataNotifier.loggedInUserData != null) {
      _userData = userDataNotifier.loggedInUserData;
    } else {
      _userData = UserData();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Profile'),
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.only(top: 20.0),
        child: Form(
          autovalidate: true,
          key: _formKey,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              LabelTextPadding(text: 'Business Information'),

              //business name
              RegularTextPadding(regText: 'Business Name'),
              _buildBusinessName(),

              //business type
              RegularTextPadding(regText: 'Business Type'),
              _buildBusinessType(),

              //Trading currency
              RegularTextPadding(regText: 'Trading Currency'),
              _buildTradingCurrency(),

              //business location
              RegularTextPadding(regText: 'Location'),
              //address 1
              _buildAddress(),
              //city
              _buildCityField(),
              //postcode
              _buildPostcode(),
              //state
              _buildStateField(),
              //country
              _buildCountry(),

              SizedBox(
                height: 20.0,
              ),
              DividerClass(),
              SizedBox(
                height: 20.0,
              ),

              //Personal information
              LabelTextPadding(
                text: 'Personal Information',
              ),
              _buildFirstNameField(),
              _buildLastNameField(),
              _buildPhoneNumberField(),
//              _buildEmailField(),
              _buildButtons(),
            ],
          ),
        ),
      ),
    );
  }

  _buildBusinessName() {
    if (_userData.businessName == null) {
      return PaddedInputTextFormField(
        hintText: 'update business name',
        onSaved: (value) {
          _userData.businessName = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.businessName,
        onSaved: (value) {
          _userData.businessName = value;
        },
      );
    }
  }

  _buildBusinessType() {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: DropdownButton(
        value: _userData.businessType == null
            ? selectedBusinessTypeDropDownValue
            : _userData.businessType,
        icon: Icon(FontAwesomeIcons.caretDown),
        elevation: 15,
        underline: Container(
          height: 2,
          color: kThemeStyleButtonFillColour,
        ),
        items: businessType
            .map(
              (businessType) => DropdownMenuItem(
                  value: businessType, child: Text(businessType)),
            )
            .toList(),
        onChanged: (newValue) {
          setState(() {
            selectedBusinessTypeDropDownValue = newValue;
            _userData.businessType = newValue;
          });
        },
      ),
    );
  }

  _buildTradingCurrency() {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: DropdownButton(
        value: _userData.tradingCurrency == null
            ? selectedCurrencyDropDownValue
            : _userData.tradingCurrency,
        icon: Icon(FontAwesomeIcons.caretDown),
        elevation: 15,
        underline: Container(
          height: 2,
          color: kThemeStyleButtonFillColour,
        ),
        items: tradingCurrency
            .map(
              (tradingCurrency) => DropdownMenuItem(
                  value: tradingCurrency, child: Text(tradingCurrency)),
            )
            .toList(),
        onChanged: (newValue) {
          setState(() {
            selectedCurrencyDropDownValue = newValue;
            _userData.tradingCurrency = newValue;
          });
        },
      ),
    );
  }

  _buildAddress() {
    if (_userData.streetAddress == null) {
      return PaddedInputTextFormField(
        hintText: 'address 1',
        onSaved: (value) {
          _userData.streetAddress = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.streetAddress,
        onSaved: (value) {
          _userData.streetAddress = value;
        },
      );
    }
  }

  _buildCityField() {
    if (_userData.city == null) {
      return PaddedInputTextFormField(
        hintText: 'update city',
        onSaved: (value) {
          _userData.city = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.city,
        onSaved: (value) {
          _userData.city = value;
        },
      );
    }
  }

  _buildPostcode() {
    if (_userData.postcode == null) {
      return PaddedInputTextFormField(
        hintText: 'update postcode',
        onSaved: (value) {
          _userData.postcode = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.postcode,
        onSaved: (value) {
          _userData.postcode = value;
        },
      );
    }
  }

  _buildStateField() {
    if (_userData.state == null) {
      return PaddedInputTextFormField(
        hintText: 'update state',
        onSaved: (value) {
          _userData.state = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.state,
        onSaved: (value) {
          _userData.state = value;
        },
      );
    }
  }

  _buildCountry() {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: DropdownButton(
        value: _userData.country == null
            ? selectedCountryDropDownValue
            : _userData.country,
        icon: Icon(FontAwesomeIcons.caretDown),
        elevation: 15,
        underline: Container(
          height: 2,
          color: kThemeStyleButtonFillColour,
        ),
        items: country
            .map(
              (country) =>
                  DropdownMenuItem(value: country, child: Text(country)),
            )
            .toList(),
        onChanged: (newValue) {
          setState(() {
            selectedCountryDropDownValue = newValue;
            _userData.country = newValue;
          });
        },
      ),
    );
  }

  //user personal info build
  _buildFirstNameField() {
    if (_userData.firstName == null) {
      return PaddedInputTextFormField(
        hintText: 'update first name',
        onSaved: (value) {
          _userData.firstName = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.firstName,
        onSaved: (value) {
          _userData.firstName = value;
        },
      );
    }
  }

  _buildLastNameField() {
    if (_userData.lastName == null) {
      return PaddedInputTextFormField(
        hintText: 'update last name',
        onSaved: (value) {
          _userData.lastName = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.lastName,
        onSaved: (value) {
          _userData.lastName = value;
        },
      );
    }
  }

  _buildPhoneNumberField() {
    if (_userData.phoneNumber == null) {
      return PaddedInputTextFormField(
        hintText: 'update phone number',
        onSaved: (value) {
          _userData.phoneNumber = value;
        },
      );
    } else {
      return PaddedInputTextFormField(
        inputValue: _userData.lastName,
        onSaved: (value) {
          _userData.phoneNumber = value;
        },
      );
    }
  }

  //build email form field
  _buildEmailField() {
    FutureBuilder<String>(
      future: AuthProvider.of(context).auth.getCurrentUserEmail(),
      // ignore: missing_return
      builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
        return PaddedEmailInputTextField(
          emailInput: snapshot.data,
          onSaved: (value) => email = value,
        );
      },
    );
  }

  _buildButtons() {
    return Padding(
      padding: const EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Buttons(
              onPressedButton: () {
                Navigator.pop(context);
              },
              buttonLabel: 'Cancel',
              buttonColour: kThemeStyleButtonFillColour,
              buttonTextStyle: kThemeStyleButton),
          SizedBox(
            width: 15.0,
          ),
          Buttons(
              onPressedButton: () => _saveUserData(context),
              buttonLabel: 'Save',
              buttonColour: kThemeStyleButtonFillColour,
              buttonTextStyle: kThemeStyleButton),
        ],
      ),
    );
  }
}

我可能会错过什么?我不确定如何解决我遇到的错误。还看到其他开发人员在网上面临类似的问题,但没有答案/线索很有效。

谢谢。

标签: firebasefluttergoogle-cloud-firestoreflutter-change-notifier

解决方案


所以我弄清楚了为什么我会收到这个错误。问题是我在我的 updateUserData() 方法中设置 isUpating ,在我的应用程序中默认设置为 true ,没有保存到数据库的初始数据。

当没有现有数据时,我必须使用

documentReference.setData(userData.toMap()) 

因为目前没有可更新的内容

我希望这可以帮助任何寻求解决方案的人。


推荐阅读