# #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? Использую ли я его в нажатой: части кнопки?