Flutter & Firebase: Error with FutureBilder - firebase

Currently i develop a Meal and Shopping App. In this App you can Add what you want to Eat next and have the secound Tab, Shopping where you can Add your Items you want to buy next. Created is that a User can invite another User to edit together the List.
I get the Error shown below. I can't figure out how to return the Container. At the void saveInviteToFirestore the user is not used do I need that it used?
Code
import 'package:flutter/material.dart';
import 'package:mealapp/models/Widgets/whenAndWhatToEat.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:intl/intl.dart';
import 'package:mealapp/models/global.dart';
import 'package:status_alert/status_alert.dart';
import 'package:firebase_auth/firebase_auth.dart';
class MealTile extends StatefulWidget {
final MealsAndWhen mealsAndWhen;
MealTile({this.mealsAndWhen});
#override
MealTileState createState() {
return MealTileState();
}
}
class MealTileState extends State<MealTile> {
String id;
final db = Firestore.instance;
String mail;
List<String> authors = [];
DateTime selectedDate = DateTime.now();
Future pickDate() async {
DateTime datepick = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime.now().add(Duration(days: -0)),
lastDate: new DateTime.now().add(Duration(days: 365)));
if (datepick != null)
setState(() {
selectedDate = datepick;
});
}
Future<String> inputData() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
return user != null ? user.uid : null;
}
Future<String> inputDataMail() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
return user != null ? user.email : null;
}
String userId;
void _getUserId() {
inputData().then((value) => setState(() {
userId = value;
}));
}
String currentMail;
void _getMail(doc) {
inputDataMail().then((value) => setState(() {
currentMail = value;
}));
}
/*void _getAuthors(DocumentSnapshot doc) async {
authors = [];
//if (await FirebaseAuth.instance.currentUser() != null) {
authors = List.from(doc.data['Authors']);
print(doc.data['authors']);
//authors.insert(0, currentMail);
//}
}*/
Widget buildItem(DocumentSnapshot doc) {
DateTime now = doc.data['Date'].toDate();
DateFormat formatter = DateFormat('dd-MM-yyyy');
String formatted = formatter.format(now);
_getUserId();
_getMail(doc);
if (doc.data['Authors'] != null) {
//_getAuthors(doc);
//print('Current mail: ' + currentMail + authors.toString() + doc.data['Author'] + doc.data['Meal']);
}
if (now.day == DateTime.now().day) { // If the Date of the meal is today
deleteData(doc, false); // Delete it!
}
// You could also change ".day" to ".hour".
// Example: if (now.day == DateTime.now().day && now.hour == DateTime.hour())
// So, if a meal is set for 2PM, it will delete at 2PM
return FutureBuilder<FirebaseUser>(
future: FirebaseAuth.instance.currentUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.hasData && snapshot != null) {
return Container(
margin: const EdgeInsets.all(8.0),
child: currentMail == doc.data['Author'] || // If the current mail is the author
List.from(doc.data['Authors']).contains(currentMail) // Or if the current mail is part of the authors
? Column( // then if true, show a Column
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'Meal:',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
Text(
'${doc.data['Meal']}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
SizedBox(height: 20),
Text(
'When:',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
onPressed: () => updateData(doc),
color: lightBlueColor,
icon: Icon(Icons.calendar_today,
color: Colors.white),
tooltip: 'Update Date',
),
Text(
formatted,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(width: 8),
FlatButton(
color: Colors.red,
onPressed: () => deleteData(doc, true),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadiusDirectional.circular(12)),
child: Row(children: <Widget>[
Text('Delete',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white)),
Icon(Icons.delete_forever, color: Colors.white),
]),
),
SizedBox(width: 8),
FlatButton(
color: Colors.blue,
onPressed: () => [
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
child: invite(doc),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(12)),
),
);
})
],
shape: RoundedRectangleBorder(
borderRadius:
BorderRadiusDirectional.circular(12)),
child: Row(children: <Widget>[
Text('Invite',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white)),
Icon(Icons.share, color: Colors.white),
]),
),
],
),
],
)
: Text(''), // if false, show an empty text widget
decoration: BoxDecoration(
color: lightBlueColor,
borderRadius: BorderRadius.all(Radius.circular(12)),
),
);
}
/*Navigator.pop(context);
return HomePage();*/
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: darkGreyColor,
body: ListView(
padding: EdgeInsets.only(top: 220),
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: db
.collection('mealList')
.orderBy('Date', descending: false) // Order by Date, not descending
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: snapshot.data.documents
.map((doc) => buildItem(doc))
.toList());
} else {
return Container();
}
},
),
],
),
);
}
/*share(BuildContext context, DocumentSnapshot doc) {
final RenderBox box = context.findRenderObject();
final dynamic date = timeago.format(doc['Date'].toDate());
Share.share(
"${doc['Meal']} - $date",
subject: doc['Meal'],
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size,
);
}*/
Widget invite(DocumentSnapshot doc) {
final _formKey = GlobalKey<FormState>();
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Center(
child: Text(
"Invite someone by mail",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
)),
SizedBox(
height: 24,
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
labelText: 'Enter the email address'),
validator: (value) {
if (value.isEmpty) {
return 'Please enter an email address';
}
return null;
},
onSaved: (value) => mail = value,
),
FlatButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
saveInviteToFirestore(doc, mail);
}
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Text("Save"),
color: redColor,
textColor: Colors.white,
),
]),
),
);
}
Future<String> getCurrentUser() async {
return await FirebaseAuth.instance.currentUser().then((value) => value.uid);
}
void saveInviteToFirestore(DocumentSnapshot doc, String email) async {
final String user = await getCurrentUser();
var list = List<String>();
list.add(email);
Firestore.instance
.collection('mealList')
.document(doc.documentID)
.updateData({"Authors": FieldValue.arrayUnion(list)});
//setState(() => id = doc.documentID);
StatusAlert.show(
context,
duration: Duration(seconds: 2),
title: 'Added',
subtitle: 'You have Added your and the Date to your List',
configuration: IconConfiguration(icon: Icons.done),
);
//Navigator.pop(context);
}
void deleteData(DocumentSnapshot doc, bool showMessage) async {
await db.collection('mealList').document(doc.documentID).delete();
setState(() => id = null);
if (showMessage) {
StatusAlert.show(
context,
duration: Duration(seconds: 2),
title: 'Deleted',
subtitle: 'You have Deleted your Meal',
configuration: IconConfiguration(icon: Icons.delete),
);
}
}
void updateData(DocumentSnapshot doc) async {
await pickDate();
await db
.collection('mealList')
.document(doc.documentID)
.updateData({'Date': selectedDate});
StatusAlert.show(
context,
duration: Duration(seconds: 2),
title: 'Updated',
subtitle: 'You have updated your Meal Date',
configuration: IconConfiguration(icon: Icons.done),
);
}
}
Error
The following assertion was thrown building FutureBuilder<FirebaseUser>(dirty, state: _FutureBuilderState<FirebaseUser>#a4504):
A build function returned null.
The offending widget is: FutureBuilder<FirebaseUser>
Build functions must never return null.
To return an empty space that causes the building widget to fill available room, return "Container()". To return an empty space that takes as little room as possible, return "Container(width: 0.0, height: 0.0)".
The relevant error-causing widget was
FutureBuilder<FirebaseUser>
lib/…/MealPlan/mealTile.dart:92
When the exception was thrown, this was the stack
#0 debugWidgetBuilderValue.<anonymous closure>
package:flutter/…/widgets/debug.dart:276

In your FutureBuilder you are not returning anything when the Future hasn't completed yet. A widget always needs to be returned whether there is data or not.
Example fix for your code:
return FutureBuilder<FirebaseUser>(
future: FirebaseAuth.instance.currentUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.hasData && snapshot != null) {
return Container(
...
);
}
//ADDED ELSE BLOCK
else {
return Container();
}
}
);
Or as #stacker suggested, you can return a CircularProgressIndicator().

Related

Flutter and Firebase Authentication problem

Flutter fellow today I have a problem with the Firebase Authentication service.
Well then let me explain the situation. I have a page that let you select a type of user, if you select "Guest" you will push through the app's dashboard page Nav() without sign-in but if select "Sign-in" app will push you to the login page Login().
class SelectUser extends StatelessWidget {
const SelectUser({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF20348F),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: const EdgeInsets.all(15.0),
margin: const EdgeInsets.all(15.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(45),
),
child: TextButton(
child: const Text('Guest'),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const Nav(),
),
(route) => false,
);
},
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
)),
),
),
Container(
padding: const EdgeInsets.all(15.0),
margin: const EdgeInsets.all(15.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(45),
),
child: TextButton(
child: const Text('Sign-In'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (contex) {
return const Login();
}));
},
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
)),
),
),
],
),
),
);
}
}
In Nav() I use BottomNavigationBarItem and have a several widget included Proflie()
inside.
I already test the sign-up, sign-out and registration function everything is perfectly fine but when I try to be tricky in Proflie() and I face...let's said the weird problem. First let's me show you the code in the Proflie().
class Profile extends StatefulWidget {
const Profile({Key? key}) : super(key: key);
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
String? _email;
DateTime? _creationTime;
DateTime? _lastSignIn;
bool? _status;
#override
Widget build(BuildContext context) {
userStatus();
return userForm();
}
userStatus() {
FirebaseAuth.instance.authStateChanges().listen((event) {
if (event == null) {
_status = false;
} else {
_status = true;
_email = FirebaseAuth.instance.currentUser!.email;
_creationTime =
FirebaseAuth.instance.currentUser!.metadata.creationTime;
_lastSignIn =
FirebaseAuth.instance.currentUser!.metadata.lastSignInTime;
}
});
}
Widget userForm() {
if (_status == true) {
return Scaffold(
appBar: defaultAppBar('Profile'),
body: Center(
child: ListView(
padding: const EdgeInsets.all(20),
children: [
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Email: $_email',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Creation Time: $_creationTime',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Last Sign-In: $_lastSignIn',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
const SizedBox(height: 45),
button('Change password', 1),
const SizedBox(height: 18),
button('Change email', 2),
const SizedBox(height: 18),
button('Sign-out', 0),
],
),
),
);
} else {
return Center(
child: ListView(
padding: const EdgeInsets.all(14),
children: <Widget>[
const SizedBox(height: 100),
Container(
margin: const EdgeInsets.all(30),
child: const Center(
child: Text(
'Please sign-in to use this Feature',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
const SizedBox(height: 50),
button('Login', 3),
const SizedBox(height: 18),
button('Register', 4),
],
),
);
}
}
Widget button(String txt, int _nav) {
Color? _color = const Color(0xFF20348F);
if (_nav == 0) {
_color = Colors.red;
}
return TextButton(
style: TextButton.styleFrom(
primary: _color,
textStyle: const TextStyle(
fontSize: 20,
),
),
child: Text(txt),
onPressed: () {
if (_nav == 0) {
FirebaseAuth.instance.signOut();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const SelectUser(),
),
(route) => false,
);
} else {
Navigator.push(context, MaterialPageRoute(builder: (contex) {
if (_nav == 1) {
return const EditPass();
} else if (_nav == 2) {
return const EditEmail();
} else if (_nav == 3) {
return const Login();
} else {
return const Register();
}
}));
}
},
);
}
}
As you can see I'm trying to use userStatus() to identify the "User" and "Guest" and that function I use FirebaseAuth.instance.authStateChanges().listen((event) to check user state in Firebase Authentication(Not really sure am I doing the right way if not please teach me how to check user state) if event == null that mean no user sign-in right now. I'm just going to set _status = false so the "Guest" should found the else case in userForm(). Otherwise _status = true this mean user is signed-in and userForm() should go to if (_status == true) case.
Now the problem is when I success to sign-in on the Login(). In Profile() I ended up got the else case of userForm() instead but that not all! When I hot reloaded the IDE it turn out now I'm in the if (_status == true) case. Yeah like said it a weird problem the first time that app loaded the page it go to false case but when hot reloaded it turn to true case. I'm not so sure the error is from Profile() or Login(). I'm just going leave the Login() then.
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final _formKey = GlobalKey<FormState>();
var _email = "";
var _password = "";
final emailController = TextEditingController();
final passwordController = TextEditingController();
bool _passwordVisible = true;
#override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return formLogin();
}
Widget formLogin() {
return Scaffold(
appBar: defaultAppBar('Sign-In'),
body: Center(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(32),
child: ListView(
children: [
buildEmail(),
const SizedBox(height: 24),
buildPassword('Password', 'Your password...'),
const SizedBox(height: 50),
button('Sign-in', 0),
const SizedBox(height: 24),
button('Sign-up', 1),
],
),
),
),
),
);
}
userLogin() async {
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(email: _email, password: _password);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const Nav(),
),
(route) => false,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.amber,
content: Text(
"Email not found",
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
),
);
} else if (e.code == 'wrong-password') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.amber,
content: Text(
"Password incorrect",
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
),
);
}
}
}
TextButton button(String txt, int nav) {
return TextButton(
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 20,
),
),
child: Text(txt),
onPressed: () {
if (nav == 0) {
if (_formKey.currentState!.validate()) {
setState(() {
_email = emailController.text;
_password = passwordController.text;
});
userLogin();
}
} else {
_formKey.currentState!.reset();
Navigator.push(context, MaterialPageRoute(builder: (contex) {
return const Register();
}));
}
},
);
}
Widget buildEmail() {
return TextFormField(
decoration: const InputDecoration(
labelText: 'Email',
hintText: 'name#example.com',
prefixIcon: Icon(Icons.mail_outline),
border: OutlineInputBorder(),
errorStyle: TextStyle(color: Colors.redAccent, fontSize: 15),
),
controller: emailController,
validator: MultiValidator([
RequiredValidator(errorText: "Email is required"),
EmailValidator(errorText: "The format of email is incorrect")
]),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
);
}
Widget buildPassword(String _txt1, String _txt2) {
return TextFormField(
obscureText: _passwordVisible,
decoration: InputDecoration(
labelText: _txt1,
hintText: _txt2,
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_passwordVisible = !_passwordVisible;
});
},
child: Icon(
_passwordVisible ? Icons.visibility : Icons.visibility_off,
),
),
prefixIcon: const Icon(Icons.vpn_key_outlined),
border: const OutlineInputBorder(),
errorStyle: const TextStyle(color: Colors.redAccent, fontSize: 15),
),
controller: passwordController,
validator: RequiredValidator(errorText: "Password is required"),
textInputAction: TextInputAction.done,
);
}
}
If you guy could help me I'd gladly appreciated.
If you can create a .gist i would be of help to u, also in your profile page i can see issue's that u r listening to the user changes in the build, its very unpractical to add it in the build because flutter will call the build method multiple times , build should be clean, also potential memory leaks are there since u r not disposing the streams.

Firebase List view is not displayed in real-time while adding data

I am storing Contact information on Firebase real-time DB after picking a contact from the phone.
When I add the data which is displayed using ListView and DataSnapshot the data is not refreshed in real-time until I restart the Activity. The ListView loads and displays all the data without any problem. How do I resolve this issue?
My screen looks like this:
Code for Screen:
import 'package:epicare/CaregiverClass.dart';
import 'package:epicare/Homepage.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_switch/flutter_switch.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:contact_picker/contact_picker.dart';
//Check contacts permission
Future<PermissionStatus> _getPermission() async {
final PermissionStatus permission = await Permission.contacts.status;
if (permission != PermissionStatus.granted &&
permission != PermissionStatus.denied) {
final Map<Permission, PermissionStatus> permissionStatus =
await [Permission.contacts].request();
return permissionStatus[Permission.contacts] ??
PermissionStatus.undetermined;
} else {
return permission;
}
}
class CaregiverScreen extends StatefulWidget {
#override
_CaregiverScreenState createState() => _CaregiverScreenState();
}
class _CaregiverScreenState extends State<CaregiverScreen> {
//Firebase
FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final ref = FirebaseDatabase.instance.reference();
User cuser = FirebaseAuth.instance.currentUser;
final fb = FirebaseDatabase.instance.reference().child("User_data");
List <CaregiverList> list = List();
// Adding data into Firebase
void addData(String name, String number) {
print("Saving data to firebase");
ref.child('User_data').child(cuser.uid).child("caregivers").push().set({'Caregiver_Name': name, 'Caregiver_Number': number});
}
// Get location
Position _currentPosition;
String _currentAddress;
final Geolocator geolocator = Geolocator()..forceAndroidLocationManager;
#override
void initState() {
// Firebase
fb.child(cuser.uid).child("caregivers").once().then((DataSnapshot snapshot)
{
var data = snapshot.value;
list.clear();
data.forEach((key,value){
print(value['Caregiver_Name']);
CaregiverList contact_list = new CaregiverList(
name: value['Caregiver_Name'],
phone_number: value['Caregiver_Number'],
isActive: true,
key: key,
);
list.add(contact_list);
});
setState(() {
});
}
);
super.initState();
}
final ContactPicker _contactPicker = new ContactPicker();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
//Size size = MediaQuery.of(context).size;
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: const Color(0xffE5E0A1),
elevation: 0,
centerTitle: true,
title: Text(
"Add Caregiver",
style: TextStyle(
fontSize: 15.0,
color: Colors.black,
fontFamily: 'Montserrat',
fontWeight: FontWeight.normal,
),
),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.black,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return Homepage();
},
),
);
},
),
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
MaterialButton(
onPressed: () async {
final PermissionStatus permissionStatus =
await _getPermission();
if (permissionStatus == PermissionStatus.granted) {
//We can now access our contacts here
Contact contact = await _contactPicker.selectContact();
print("Contact name: ${contact.fullName}");
print("Contact number: ${contact.phoneNumber}");
List<String> num =
contact.phoneNumber.toString().split('(Work)');
print(num);
print(num[0]);
final pattern = RegExp('\\s+');
num[0].replaceAll(pattern, '');
num[0].replaceAll(new RegExp('-'),'');
addData(contact.fullName.toString(),num[0]);
} else {
//If permissions have been denied show standard cupertino alert dialog
showDialog(
context: context,
builder: (BuildContext context) =>
CupertinoAlertDialog(
title: Text('Permissions error'),
content: Text('Please enable contacts access '
'permission in system settings'),
actions: <Widget>[
CupertinoDialogAction(
child: Text('OK'),
onPressed: () =>
Navigator.of(context).pop(),
)
],
));
}
},
color: const Color(0xffd4d411),
textColor: Colors.white,
child: Icon(
Icons.add,
size: 32,
),
padding: EdgeInsets.all(3),
shape: CircleBorder(),
),
Text(
'Add a Caregiver',
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 13,
color: const Color(0xff000000),
height: 1.5384615384615385,
fontWeight: FontWeight.w600),
textHeightBehavior:
TextHeightBehavior(applyHeightToFirstAscent: false),
textAlign: TextAlign.left,
)
],
),
list.length == 0 ? Center(child: Text("Please add Caregivers"))
: ListView.separated(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) {
return _caregiverWidget(list[index].name,list[index].phone_number,list[index].isActive,list[index].key
);
},
separatorBuilder: (_, __) => Container(),
itemCount: list.length),
// _contact == null ? Container() : CaregiversList(_contact.fullName),
],
),
),
),
);
}
Widget _caregiverWidget( String name, String phone_number, bool isActive, String key
) {
print(name);
var c = name.split(' ');
print(c[0]);
var caregiver = c[0];
var output = getInitials(string: caregiver, limitTo: 1);
print(output);
return GestureDetector(
onLongPress: (){},
onTap: (){},
child: Card(
elevation: 0,
child: Container(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 27),
child: Row(
//crossAxisAlignment: CrossAxisAlignment.center,
//mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CircleAvatar(
radius: 24,
backgroundColor: const Color(0xffd4d411),
child: CircleAvatar(
radius: 22,
backgroundColor: Colors.white,
child: Text(
output,
style: TextStyle(
fontFamily: 'Segoe UI',
fontSize: 20,
color: const Color(0xff000000),
),
),
),
),
SizedBox(width: 19),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
caregiver,
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 13,
color: const Color(0xff000000),
height: 1.5384615384615385,
fontWeight: FontWeight.w600),
textHeightBehavior:
TextHeightBehavior(applyHeightToFirstAscent: false),
textAlign: TextAlign.left,
),
isActive
? Text(
"Activated",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 10,
color: const Color(0x80232425),
fontWeight: FontWeight.w500),
textAlign: TextAlign.left,
)
: Text(
"Disabled",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 10,
color: const Color(0x80232425),
fontWeight: FontWeight.w500),
textAlign: TextAlign.left,
),
],
),
SizedBox(width: 143),
FlutterSwitch(
width: 40.0,
height: 20.0,
value: isActive,
toggleSize: 15,
borderRadius: 40.0,
padding: 2.0,
showOnOff: false,
activeColor: const Color(0xffd4d411),
activeToggleColor: Colors.white,
inactiveColor: const Color(0xffDDDBAF),
inactiveToggleColor: Colors.white,
onToggle: (value) {
print(value);
setState(() {
isActive = value;
// _careList.removeAt(index);
// _careList.insert(index, _caregiver);
});
},
),
],
),
),
),
);
}
String getInitials({String string, int limitTo}) {
var buffer = StringBuffer();
var split = string.split(' ');
for (var i = 0; i < (limitTo ?? split.length); i++) {
buffer.write(split[i][0]);
}
return buffer.toString();
}
}
The issue is that this part:
fb.child(cuser.uid).child("caregivers").once()..
is only getting the value once.
To se realtime updates you should either use a listener like here:
CollectionReference reference = Firestore.instance.collection('caregivers');
reference.snapshots().listen((querySnapshot) {
querySnapshot.documentChanges.forEach((change) {
// Do something with change
});
});
or a StreamBuilder like here:
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('caregivers').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['name']),
);
}).toList(),
);
},
);
for the RTDB the StreamBuilder would look like this:
StreamBuilder(
stream: _database.reference().child('caregivers').onValue,
builder: (context, event) {
if (event.hasData &&
!event.hasError &&
event.data.snapshot.value != null) {
DataSnapshot snapshot = event.data.snapshot;
}
})
the listener would be like:
_database.reference().child('caregivers').onValue.listen((event){
})
onValue will give you everytime the whole list so you need to empty it before you add again every item:
var data = event.snapshot.value;
list= List(); //Clear the list here
data.forEach((key, value) {
print(value['Caregiver_Name']);
CaregiverList contact_list = new CaregiverList(
name: value['Caregiver_Name'],
phone_number: value['Caregiver_Number'],
isActive: true,
key: key,
);
list.add(contact_list);
});

A non-null String must be provided to a Text widget flutter

I have this problem with this code. I tried to solve the problem, but I did not succeed. Please Help
Please see the screenshots to understand the problem well
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 370 pos 10: 'data != null'
Pictures description error
null in firebase
The users email address.Will be null if signing in anonymously.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
class ChatScreen extends StatefulWidget {
static const Id = 'chat_screen';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
// ignore: deprecated_member_use
final _firestore = Firestore.instance;
final _auth = FirebaseAuth.instance;
// ignore: deprecated_member_use
FirebaseUser loggedInUser;
String messageText;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
// ignore: await_only_futures
final user = await _auth.currentUser;
if (user != null) {
loggedInUser = user;
print(loggedInUser.email);
}
} catch (e) {
print(e);
}
}
// void getMessages() async {
// // ignore: deprecated_member_use
// final messages = await _firestore.collection('Messages').getDocuments();
// // ignore: deprecated_member_use
// for (var message in messages.docs) {
// print(message.data());
// }
// }
void messagesStream() async {
await for (var snapshot in _firestore.collection('Messages').snapshots()) {
for (var message in snapshot.docs) {
print(message.data());
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
messagesStream();
//_auth.signOut();
//Navigator.pop(context);
}),
],
title: Text('⚡️Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('Messages').snapshots(),
// ignore: missing_return
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
));
}
// ignore: deprecated_member_use
final messages = snapshot.data.documents;
List<Messagebubble> messagebubbles = [];
for (var message in messages) {
final messageText = message.data()['text'];
final messagesendar = message.data()['Sender'];
final messagebubble = Messagebubble(
sendar: messagesendar,
text: messageText,
);
messagebubbles.add(messagebubble);
}
return Expanded(
child: ListView(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 20.0,
),
children: messagebubbles,
),
);
},
),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
_firestore.collection('Messages').add({
'text': messageText,
'Sender': loggedInUser,
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class Messagebubble extends StatelessWidget {
Messagebubble({
Key key,
this.sendar,
this.text,
}) : super(key: key);
final String sendar;
final String text;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
children: [
Text(
sendar,
style: TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
),
Material(
borderRadius: BorderRadius.circular(30.0),
elevation: 5.0,
color: Colors.lightBlueAccent,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 20.0,
),
child: Text(
text,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
),
),
],
),
);
}
}
You just need to check whether the text that you are passing is null or not. If it is null, you can show that the user is Anonymous.
final messageText = message.data()['text'];
final messagesendar = message.data()['Sender'] ?? 'Anonymous'; // If null then use 'Anonymous'
final messagebubble = Messagebubble(
sendar: messagesendar,
text: messageText,
);
Flutter doesn't allow you to pass null to Text widgets.

Flutter Firebase Iterator Error with FutureBuilder

Running my App on Android and iOS I get the Error shown below. What I want to do, give every Data that get's added a Author, the Author should be the Mail Adress the User Registers with, so by Inviting other Users get Access to this Data.
Another Problem is that in Line 302 the String "user" is unused.
Do i really need to use this String?
Error
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building FutureBuilder<FirebaseUser>(dirty, state: _FutureBuilderState<FirebaseUser>#7f7ed):
The getter 'iterator' was called on null.
Receiver: null
Tried calling: iterator
The relevant error-causing widget was
FutureBuilder<FirebaseUser>
lib/…/MealPlan/mealTile.dart:92
When the exception was thrown, this was the stack
Code
import 'package:flutter/material.dart';
import 'package:mealapp/models/Widgets/whenAndWhatToEat.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:intl/intl.dart';
import 'package:mealapp/models/global.dart';
import 'package:status_alert/status_alert.dart';
import 'package:firebase_auth/firebase_auth.dart';
class MealTile extends StatefulWidget {
final MealsAndWhen mealsAndWhen;
MealTile({this.mealsAndWhen});
#override
MealTileState createState() {
return MealTileState();
}
}
class MealTileState extends State<MealTile> {
String id;
final db = Firestore.instance;
String mail;
List<String> authors = [];
DateTime selectedDate = DateTime.now();
Future pickDate() async {
DateTime datepick = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime.now().add(Duration(days: 0)),
lastDate: new DateTime.now().add(Duration(days: 365)));
if (datepick != null)
setState(() {
selectedDate = datepick;
});
}
Future<String> inputData() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
return user != null ? user.uid : null;
}
Future<String> inputDataMail() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
return user != null ? user.email : null;
}
String userId;
void _getUserId() {
inputData().then((value) => setState(() {
userId = value;
}));
}
String currentMail;
void _getMail(doc) {
inputDataMail().then((value) => setState(() {
currentMail = value;
}));
}
/*void _getAuthors(DocumentSnapshot doc) async {
authors = [];
//if (await FirebaseAuth.instance.currentUser() != null) {
authors = List.from(doc.data['Authors']);
print(doc.data['authors']);
//authors.insert(0, currentMail);
//}
}*/
Widget buildItem(DocumentSnapshot doc) {
DateTime now = doc.data['Date'].toDate();
DateFormat formatter = DateFormat('dd-MM-yyyy');
String formatted = formatter.format(now);
_getUserId();
_getMail(doc);
if (doc.data['Authors'] != null) {
//_getAuthors(doc);
//print('Current mail: ' + currentMail + authors.toString() + doc.data['Author'] + doc.data['Meal']);
}
if (now.day == DateTime.now().day) { // If the Date of the meal is today
deleteData(doc, false); // Delete it!
}
// You could also change ".day" to ".hour".
// Example: if (now.day == DateTime.now().day && now.hour == DateTime.hour())
// So, if a meal is set for 2PM, it will delete at 2PM
return FutureBuilder<FirebaseUser>(
future: FirebaseAuth.instance.currentUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.hasData && snapshot != null) {
return Container(
margin: const EdgeInsets.all(8.0),
child: currentMail == doc.data['Author'] || // If the current mail is the author
List.from(doc.data['Authors']).contains(currentMail) // Or if the current mail is part of the authors
? Column( // then if true, show a Column
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'Meal:',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
Text(
'${doc.data['Meal']}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
SizedBox(height: 20),
Text(
'When:',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
onPressed: () => updateData(doc),
color: lightBlueColor,
icon: Icon(Icons.calendar_today,
color: Colors.white),
tooltip: 'Update Date',
),
Text(
formatted,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(width: 8),
FlatButton(
color: Colors.red,
onPressed: () => deleteData(doc, true),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadiusDirectional.circular(12)),
child: Row(children: <Widget>[
Text('Delete',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white)),
Icon(Icons.delete_forever, color: Colors.white),
]),
),
SizedBox(width: 8),
FlatButton(
color: Colors.blue,
onPressed: () => [
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
child: invite(doc),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(12)),
),
);
})
],
shape: RoundedRectangleBorder(
borderRadius:
BorderRadiusDirectional.circular(12)),
child: Row(children: <Widget>[
Text('Invite',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white)),
Icon(Icons.share, color: Colors.white),
]),
),
],
),
],
)
: Text(''), // if false, show an empty text widget
decoration: BoxDecoration(
color: lightBlueColor,
borderRadius: BorderRadius.all(Radius.circular(12)),
),
);
}
else {
return CircularProgressIndicator();
}
/*Navigator.pop(context);
return HomePage();*/
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: darkGreyColor,
body: ListView(
padding: EdgeInsets.only(top: 220),
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: db
.collection('mealList')
.orderBy('Date', descending: false) // Order by Date, not descending
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: snapshot.data.documents
.map((doc) => buildItem(doc))
.toList());
} else {
return Container();
}
},
),
],
),
);
}
/*share(BuildContext context, DocumentSnapshot doc) {
final RenderBox box = context.findRenderObject();
final dynamic date = timeago.format(doc['Date'].toDate());
Share.share(
"${doc['Meal']} - $date",
subject: doc['Meal'],
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size,
);
}*/
Widget invite(DocumentSnapshot doc) {
final _formKey = GlobalKey<FormState>();
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Center(
child: Text(
"Invite someone by mail",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
)),
SizedBox(
height: 24,
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
labelText: 'Enter the email address'),
validator: (value) {
if (value.isEmpty) {
return 'Please enter an email address';
}
return null;
},
onSaved: (value) => mail = value,
),
FlatButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
saveInviteToFirestore(doc, mail);
}
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Text("Save"),
color: redColor,
textColor: Colors.white,
),
]),
),
);
}
Future<String> getCurrentUser() async {
return await FirebaseAuth.instance.currentUser().then((value) => value.uid);
}
void saveInviteToFirestore(DocumentSnapshot doc, String email) async {
final String user = await getCurrentUser();
var list = List<String>();
list.add(email);
Firestore.instance
.collection('mealList')
.document(doc.documentID)
.updateData({"Authors": FieldValue.arrayUnion(list)});
//setState(() => id = doc.documentID);
StatusAlert.show(
context,
duration: Duration(seconds: 2),
title: 'Added',
subtitle: 'You have Added your and the Date to your List',
configuration: IconConfiguration(icon: Icons.done),
);
//Navigator.pop(context);
}
void deleteData(DocumentSnapshot doc, bool showMessage) async {
await db.collection('mealList').document(doc.documentID).delete();
setState(() => id = null);
if (showMessage) {
StatusAlert.show(
context,
duration: Duration(seconds: 2),
title: 'Deleted',
subtitle: 'You have Deleted your Meal',
configuration: IconConfiguration(icon: Icons.delete),
);
}
}
void updateData(DocumentSnapshot doc) async {
await pickDate();
await db
.collection('mealList')
.document(doc.documentID)
.updateData({'Date': selectedDate});
StatusAlert.show(
context,
duration: Duration(seconds: 2),
title: 'Updated',
subtitle: 'You have updated your Meal Date',
configuration: IconConfiguration(icon: Icons.done),
);
}
}

getting data from firebase gives null but after hot reload work fine

after I got my data from firebase the data is null but if I hot reload it works fine. if I comment the lines with the issues the code work fine and submit data correctly to firebase
I tried many methods trying to initState to setState but no use.
I even assumed the build was doen before getting the data from firebase but initState should solve this issue as far as I know. I think i'm missing something here. :(
EDIT:
this is my new attemet useing futureBuilder still the widget loads before the data
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),
),
],
);
});
}
You are trying to get the document in async task and you are using that value in view(widget). Until the document is fetched from Firebase, the value of document will be null.
Possible solutions:
Use null checks and handle in widget (Not recommend)
Use FutureBuilder which is perfect for your use case. For example, refer
I edited your code. Have a look
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();
}
});
}
}

Resources