Введенные вручную данные не сохраняются в документе Firebase

# #firebase #flutter #google-cloud-firestore

Вопрос:

У меня есть экран с несколькими текстовыми полями, и некоторые из них заполняются при его создании. Это делается в функции initState (). Когда я ввожу данные в пустые текстовые поля, а затем сохраняю данные в документе firebase, в документ сохраняются только данные, введенные вручную после создания экрана. Ниже приведен код для экрана. Пожалуйста, помогите с этим.

 final _firebaseAuthUser = FirebaseAuth.instance.currentUser;
final agentsRef = FirebaseFirestore.instance.collection(('agents'));
final agencyRef = FirebaseFirestore.instance.collection(('agency'));

class AgentProfileScreen extends StatefulWidget {
  static const String id = 'agent_profile_screen';
  final Agents agents;

  AgentProfileScreen([this.agents]);

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

class _AgentProfileScreenState extends State<AgentProfileScreen> {
  //final _auth = FirebaseAuth.instance;
  final _db = FirebaseFirestore.instance;

  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  final fNameController = TextEditingController();
  final lNameController = TextEditingController();
  final address1Controller = TextEditingController();
  final address2Controller = TextEditingController();
  final cityController = TextEditingController();
  final stateController = TextEditingController();
  final zipController = TextEditingController();
  final cellPhoneController = TextEditingController();
  final officePhoneController = TextEditingController();
  final agencyController = TextEditingController();

  @override
  void dispose() {
    emailController.dispose();
    passwordController.dispose();
    fNameController.dispose();
    lNameController.dispose();
    address1Controller.dispose();
    address2Controller.dispose();
    cityController.dispose();
    stateController.dispose();
    zipController.dispose();
    cellPhoneController.dispose();
    officePhoneController.dispose();
    agencyController.dispose();
    super.dispose();
  }

  bool showSpinner = false;
  String email;
  String password;
  String fName;
  String lName;
  String address1;
  String address2;
  String city;
  String state;
  String zip;
  String cellPhone;
  String officePhone;
  String agency;

  String _currentAgentState;
  String _currentAgency;

  getCurrentAgentProfile() async {
    final DocumentSnapshot currentAgentProfile =
        await agentsRef.doc(globals.currentUid).get();

    //String currentAgencyId = currentAgentProfile.data()["agencyId"];
    final DocumentSnapshot currentAgencyProfile =
        await agencyRef.doc(globals.agencyId).get();

    if (globals.newAgent == true) {
      emailController.text = "";
      fNameController.text = "";
      lNameController.text = "";
      address1Controller.text = currentAgencyProfile.data()['address1'];
      address2Controller.text = currentAgencyProfile.data()['address2'];
      cityController.text = currentAgencyProfile.data()['city'];
      stateController.text = currentAgencyProfile.data()['state'];
      globals.currentAgencyState = currentAgencyProfile.data()['state'];
      zipController.text = currentAgencyProfile.data()['zipCode'].toString();
      cellPhoneController.text = currentAgencyProfile.data()['cellPhone'];
      officePhoneController.text = currentAgencyProfile.data()['officePhone'];
      agencyController.text = currentAgencyProfile.data()['name'];
    } else {
      // existing record
      // Updates Controllers
      emailController.text = currentAgentProfile.data()["email"];
      fNameController.text = currentAgentProfile.data()['fName'];
      lNameController.text = currentAgentProfile.data()['lName'];
      address1Controller.text = currentAgentProfile.data()['address1'];
      address2Controller.text = currentAgentProfile.data()['address2'];
      cityController.text = currentAgentProfile.data()['city'];
      stateController.text = currentAgentProfile.data()['state'];
      zipController.text = currentAgentProfile.data()['zipCode'].toString();
      cellPhoneController.text = currentAgentProfile.data()['cellPhone'];
      officePhoneController.text = currentAgentProfile.data()['officePhone'];
      agencyController.text = currentAgentProfile.data()['agency'];

      // Updates State
      new Future.delayed(Duration.zero, () {
        final agentProvider =
            Provider.of<AgentProvider>(context, listen: false);
        agentProvider.loadValues(widget.agents);
      });
    }
  }

  List<DropdownMenuItem<String>> _dropDownState;

  List<DropdownMenuItem<String>> getDropDownState() {
    List<DropdownMenuItem<String>> items = [];
    for (String state in globals.states) {
      items.add(new DropdownMenuItem(
          value: state,
          child: new Text(
            state,
          )));
    }
    return items;
  }

  void changedDropDownState(String selected_state) {
    setState(() {
      _currentAgentState = selected_state;
    });
    globals.selectedAgentState = selected_state;
  }

  void changedDropDownAgency(String selected_agency) {
    setState(() {
      _currentAgency = selected_agency;
    });
    globals.selectedAgency = selected_agency;
  }

  @override
  void initState() {
    getCurrentAgentProfile();
    _currentAgentState = globals.currentAgentState;
    _currentAgency = globals.agencyId;
    _currentAgentState = globals.currentAgencyState;
    super.initState();

    _dropDownState = getDropDownState();
  }

  @override
  Widget build(BuildContext context) {
    // Get the stream of agents created in main.dart
    final agentProvider = Provider.of<AgentProvider>(context);
    final _firestoreService = FirestoreService();
    String _chosenState = 'Select State';

    return Scaffold(
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Image.asset('assets/images/Appbar_logo.png',
                fit: BoxFit.cover, height: 56),
          ],
        ),
      ),
      backgroundColor: Colors.white,
      body: SafeArea(
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Column(
              //mainAxisAlignment: MainAxisAlignment.center,
              //crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Text(
                  'Agent Profile',
                  style: TextStyle(
                    fontSize: 30,
                  ),
                ),
                SizedBox(
                  height: 8.0,
                ),
                // Email entry text field
                TextField(
                  controller: fNameController,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changefName(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'First Name', labelText: 'First Name'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: lNameController,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changelName(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Last Name', labelText: 'Last Name'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                Container(
                  child: StreamBuilder(
                      stream: _db.collection('agency').snapshots(),
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        if (snapshot.data == null) {
                          return Center(
                            child: CircularProgressIndicator(),
                          );
                        } else {
                          return new DropdownButton<String>(
                            hint: new Text("Select Agency"),
                            value: _currentAgency,
                            onChanged: changedDropDownAgency,
                            items: snapshot.data.docs
                                .map<DropdownMenuItem<String>>((document) {
                              return new DropdownMenuItem<String>(
                                value: document.id,
                                child: new Text(document.data()['name']),
                              );
                            }).toList(),
                          );
                        }
                        ;
                      }),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: address1Controller,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeaddress1(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Address 1', labelText: 'Address 1'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: address2Controller,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeaddress2(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Address 2', labelText: 'Address 2'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: cityController,
                  keyboardType: TextInputType.emailAddress,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changecity(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'City', labelText: 'City'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                DropdownButton(
                  value: _currentAgentState,
                  items: _dropDownState,
                  hint: Text('Choose State'),
                  onChanged: changedDropDownState,
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: zipController,
                  keyboardType: TextInputType.phone,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changezipCode(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Zip Code', labelText: 'Zip Code'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: cellPhoneController,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changecellPhone(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Cell Phone', labelText: 'Cell Phone'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: officePhoneController,
                  keyboardType: TextInputType.emailAddress,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeofficePhone(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Office Phone', labelText: 'Office Phone'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                RoundedButton(
                  title: 'Save',
                  colour: Colors.blueAccent,
                  onPressed: () async {
                    setState(() {
                      showSpinner = true;
                    });
                    try {
                      agentProvider.saveAgent();
                      globals.newAgent = false;
                      globals.currentAgentState = _currentAgentState;
                      await _firestoreService.saveDeviceToken();
                      Navigator.pushNamed(context, Home_Screen.id);

                      setState(() {
                        showSpinner = false;
                      });
                    } catch (e) {
                      // todo: add better error handling
                      print(e);
                    }
                  },
                ),
                SizedBox(
                  height: 8.0,
                ),

                (widget != null)
                    ? RoundedButton(
                        title: 'Delete',
                        colour: Colors.red,
                        onPressed: () async {
                          setState(() {
                            showSpinner = true;
                          });
                          try {
                            agentProvider.deleteAgent(globals.currentUid);
                            Navigator.pushNamed(
                                context, AgentDashboardScreen.id);

                            setState(() {
                              showSpinner = false;
                            });
                          } catch (e) {
                            // todo: add better error handling
                            print(e);
                          }
                        },
                      )
                    : Container()
              ],
            ),
          ),
        ),
      ),
    );
  }
}
 

Ниже приведен код поставщика.

 class AgentProvider with ChangeNotifier {
  final firestoreService = FirestoreService();
  final agencyRef = FirebaseFirestore.instance.collection(('agency'));

  String _fName;
  String _lName;
  String _address1;
  String _address2;
  String _city;
  String _state;
  int _zipCode;
  String _cellPhone;
  String _officePhone;
  String _agencyId;
  String _agency;

  //Getters
  String get fName => _fName;
  String get lName => _lName;
  String get address1 => _address1;
  String get address2 => _address2;
  String get city => _city;
  String get state => globals.selectedAgentState;
  int get zipCode => _zipCode;
  String get cellPhone => _cellPhone;
  String get officePhone => _officePhone;
  String get agencyId => globals.agencyId;
  String get agency => _agency;

  //Setters

  changefName(String value) {
    _fName = value;
    notifyListeners();
  }

  changelName(String value) {
    _lName = value;
    notifyListeners();
  }

  changeaddress1(String value) {
    _address1 = value;
    notifyListeners();
  }

  changeaddress2(String value) {
    _address2 = value;
    notifyListeners();
  }

  changecity(String value) {
    _city = value;
    notifyListeners();
  }

  changestate(String value) {
    _state = value;
    notifyListeners();
  }

  // Convert String to int
  changezipCode(String value) {
    _zipCode = int.parse(value);
    notifyListeners();
  }

  // Convert String to int
  changecellPhone(String value) {
    _cellPhone = value;
    notifyListeners();
  }

  // Convert String to int
  changeofficePhone(String value) {
    _officePhone = value;
    notifyListeners();
  }

  changeAgency(String value) {
    _agency = value;
    notifyListeners();
  }

  loadValues(Agents agents) {
    _fName = agents.fName;
    _lName = agents.lName;
    _address1 = agents.address1;
    _address2 = agents.address2;
    _city = agents.city;
    _state = globals.selectedAgentState;
    _zipCode = agents.zipcode;
    _cellPhone = agents.cellPhone;
    _officePhone = agents.officePhone;
    _agencyId = globals.agencyId;
    _agency = agents.agency;
  }

  saveAgent() async {
    final newAgent = new Map();
    if (globals.newAgent == true) {
      final DocumentSnapshot currentAgencyProfile =
          await agencyRef.doc(globals.agencyId).get();
      var newAgent = Agents(
          agentId: globals.currentUid,
          fName: _fName,
          lName: _lName,
          address1: currentAgencyProfile.data()['address1'],
          address2: currentAgencyProfile.data()['address2'],
          city: currentAgencyProfile.data()['city'],
          state: globals.selectedAgentState,
          zipcode: currentAgencyProfile.data()['zipCode'],
          cellPhone: currentAgencyProfile.data()['cellPhone'],
          officePhone: currentAgencyProfile.data()['officePhone'],
          agencyId: globals.agencyId,
          agency: agency);
      firestoreService.saveAgent(newAgent);
    } else {
      var newAgent = Agents(
          agentId: globals.currentUid,
          fName: _fName,
          lName: _lName,
          address1: _address1,
          address2: _address2,
          city: _city,
          state: globals.selectedAgentState,
          zipcode: _zipCode,
          cellPhone: _cellPhone,
          officePhone: _officePhone,
          agencyId: globals.agencyId,
          agency: agency);
      firestoreService.saveAgent(newAgent);
    }
    //firestoreService.saveAgent(newAgent);

    _fName = "";
    _lName = "";
    _address1 = "";
    _address2 = "";
    _city = "";
    _state = "";
    _zipCode = null;
    _cellPhone = "";
    _officePhone = "";
    _agencyId = "";
    _agency = "";
  }
 

Вот функция saveAgent. Я действительно не думаю, что в этом проблема, но в любом случае она здесь.

 Future<void> saveAgent(Agents agents) {
    return _db.collection('agents').doc(globals.currentUid).set(agents.toMap());
  }
 

Комментарии:

1. опубликуйте свой FirestoreService.saveAgent() метод

2. @DarShan спасибо вам за ваш ответ. Я добавил функцию, но я не думаю, что это проблема, так как данные сохраняются… просто не те данные, которые я ввожу вручную.

Ответ №1:

initState предназначена для синхронной функции, и поскольку выполнение вашей асинхронной функции займет некоторое время, она будет работать не так, как вы ожидаете. Для вызова асинхронной функции используйте FutureBuilder виджет внутри вашей build функции.

Комментарии:

1. спасибо вам за ваш ответ. Где и как я могу использовать FutureBuilder? Использую ли я его в нажатой: части кнопки?