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(),//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,);
    }
  }

  _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,items: TradingCurrency
            .map(
              (TradingCurrency) => DropdownMenuItem(
                  value: TradingCurrency,child: Text(TradingCurrency)),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,);
    }
  }

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

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

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

  _buildCountry() {
    return Padding(
      padding: const EdgeInsets.all(20.0),child: DropdownButton(
        value: _userData.country == null
            ? selectedCountryDropDownValue
            : _userData.country,items: country
            .map(
              (country) =>
                  DropdownMenuItem(value: country,child: Text(country)),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,);
    }
  }

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

  _buildPhoneNumberField() {
    if (_userData.phoneNumber == null) {
      return PaddedInputTextFormField(
        hintText: 'update phone number',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',);
  }
}

我可能会丢失什么?我不确定如何解决我收到的错误。还看到其他在线开发人员也遇到了类似的问题,但是没有答案/线索很奏效。

谢谢。

解决方法

所以我弄清楚了为什么会出现该错误。问题是我在updateUserData()方法中将isUpating设置为true,默认情况下,当在我的应用程序中没有初始数据保存到数据库时,该值为true。

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

documentReference.setData(userData.toMap()) 

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

我希望这对寻求解决方案的人有所帮助。