从firebase获取数据后,该数据为空,但如果我进行热重装,则可以正常工作。如果我对有问题的行进行注释,则代码可以正常工作并将数据正确提交到Firebase
我尝试了许多尝试将initState设置为setState的方法,但是没有用。
我什至以为在从Firebase获取数据之前就已经完成了构建,但据我所知initState应该解决此问题。我想我在这里错过了一些东西。 :(
编辑: 这是我使用futureBuilder的新属性,仍然在数据之前加载小部件
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_test/flutter_test.dart';
class UnlockDoor extends StatefulWidget {
UnlockDoorState createState() => new UnlockDoorState();
}
class UnlockDoorState extends State<UnlockDoor> {
final formKey = GlobalKey<FormState>();
String building;
String room;
String name;
String email;
DateTime created;
String comment;
String uid;
@override
void initState() {
FirebaseAuth.instance.currentUser().then((FirebaseUser user) {
this.uid = user.uid;
});
Firestore.instance.collection('Users').document(uid).get().then((data) {
this.name = data['Name'];
this.email = data['Email'];
this.building = data['Building'];
this.room = data['Room'];
});
print("uid $uid");
super.initState();
}
void validateAndSubmit() async {
created = DateTime.now();
formKey.currentState.save();
await Firestore.instance
.collection('Requests')
.document('UnlockDoor')
.collection('UnlockDoor')
.document()
.setData({
'Email': email,
'Name': name,
'Building': building,
'Room': room,
'Comment': comment,
'Status': "Pending",
'Created': created,
'Housing_Emp': "",
'UID': uid
});
Navigator.of(context).pop();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Unlock Door Request"),
),
body: new FutureBuilder<DocumentSnapshot>(
future: Firestore.instance.collection('Users').document(uid).get(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.done:
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else {
print("why give null $name");
return new Container(
padding: EdgeInsets.only(top: 60.0, left: 20.0, right: 20.0),
child: new Form(
key: formKey,
child: new ListView(
children: <Widget>[
Text(
'Requesting Door Unlock:',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 15.0),
Text(
"building: $building, Room: $room",
style: TextStyle(
fontSize: 15.0,
fontStyle: FontStyle.italic,
),
),
TextFormField(
maxLength: 200,
onSaved: (value) => comment = value,
decoration: InputDecoration(
labelText: 'Comment (optional)',
labelStyle: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
),
Container(
height: 50.0,
width: 130.0,
child: RaisedButton(
child: Text(
'Send Request',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
splashColor: Colors.lightGreen,
onPressed: () {
_handlePressed(context);
}),
),
],
),
),
);
}
}
},
),
);
}
void _handlePressed(BuildContext context) {
confirmDialog(context).then((bool value) async {
if (value) {
validateAndSubmit();
}
});
}
}
Future<bool> confirmDialog(BuildContext context) {
return showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return new AlertDialog(
title: new Text("Send Request"),
actions: <Widget>[
new FlatButton(
child: Text("Yes"),
onPressed: () => Navigator.of(context).pop(true),
),
new FlatButton(
child: Text("No"),
onPressed: () => Navigator.of(context).pop(false),
),
],
);
});
}
答案 0 :(得分:2)
您正在尝试在 async 任务中获取document
,并且正在view(widget)中使用该值。从 Firebase 获取document
之前,文档的值为 null 。
可能的解决方案:
我编辑了您的代码。看看
class UnlockDoorState extends State<UnlockDoor> {
final formKey = GlobalKey<FormState>();
String building;
String room;
String name;
String email;
DateTime created;
String comment;
String uid;
Future data; //changed
@override
void initState() {
super.initState();
data = getDataFromFb(); //changed
}
Future<void> getDataFromFb() async { //changed
FirebaseUser user = await FirebaseAuth.instance.currentUser();
this.uid = user.uid;
var data = Firestore.instance.collection('Users').document(uid).get();
this.name = data['Name'];
this.email = data['Email'];
this.building = data['Building'];
this.room = data['Room'];
return;
}
void validateAndSubmit() async {
created = DateTime.now();
formKey.currentState.save();
await Firestore.instance
.collection('Requests')
.document('UnlockDoor')
.collection('UnlockDoor')
.document()
.setData({
'Email': email,
'Name': name,
'Building': building,
'Room': room,
'Comment': comment,
'Status': "Pending",
'Created': created,
'Housing_Emp': "",
'UID': uid
});
Navigator.of(context).pop();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Unlock Door Request"),
),
body: new FutureBuilder<DocumentSnapshot>(
future: data, //changed
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.done:
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else {
print("why give null $name");
return new Container(
padding: EdgeInsets.only(top: 60.0, left: 20.0, right: 20.0),
child: new Form(
key: formKey,
child: new ListView(
children: <Widget>[
Text(
'Requesting Door Unlock:',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 15.0),
Text(
"building: $building, Room: $room",
style: TextStyle(
fontSize: 15.0,
fontStyle: FontStyle.italic,
),
),
TextFormField(
maxLength: 200,
onSaved: (value) => comment = value,
decoration: InputDecoration(
labelText: 'Comment (optional)',
labelStyle: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
),
Container(
height: 50.0,
width: 130.0,
child: RaisedButton(
child: Text(
'Send Request',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
splashColor: Colors.lightGreen,
onPressed: () {
_handlePressed(context);
}),
),
],
),
),
);
}
}
},
),
);
}
void _handlePressed(BuildContext context) {
confirmDialog(context).then((bool value) async {
if (value) {
validateAndSubmit();
}
});
}
}