Firestore value returns only one value - firebase

whenever I try to retrieve data from firestore,only one part is called
You can see that I have a ListTile with a title and a Subtitle
Now only the data in the subtitle is being displayed and it requires no null indication
But the title requires the null indication but still it does not returns the string This is my firestore
Thank You
// ...
class SearchPage extends StatefulWidget {
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
TextEditingController searchController = TextEditingController();
Future<QuerySnapshot> searchResultsFuture;
handleSearch(String query){
Future<QuerySnapshot> users = usersReference.where("profilename",isGreaterThanOrEqualTo: query ).getDocuments();
setState(() {
searchResultsFuture = users;
});
//searchResultsFuture = users;
}
clearSearch(){
searchController.clear();
}
AppBar buildSearchField(){
return AppBar(
backgroundColor: Colors.white,
title: TextFormField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search Your Friends",
filled: true,
prefixIcon: Icon(
Icons.account_box,
size: 28.0,
),
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: clearSearch,
),
),
onFieldSubmitted: handleSearch,
),
);
}
Container buildNoContent(){
final Orientation orientation = MediaQuery.of(context).orientation;
return Container(
child: ListView(
shrinkWrap: true,
children: <Widget>[
Icon(Icons.group, color: Colors.white,size: orientation == Orientation.portrait ? 400.0 : 200.0 ,),
Text("Find Users",textAlign: TextAlign.center,style: TextStyle(color: Colors.white,fontStyle: FontStyle.italic,fontWeight: FontWeight.w600,fontSize: 65.0),),
],
),
);
}
buildSearchResults() {
return FutureBuilder(
future: searchResultsFuture,
builder: (context, snapshot){
if(!snapshot.hasData){
return circularProgress();
}
List<UserResult> searchResults = [];
snapshot.data.documents.forEach((doc){
User user = User.fromDocument(doc);
UserResult searchResult = UserResult(user);
searchResults.add(searchResult);
});
return ListView(
children: searchResults,
);
}
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor.withOpacity(0.8) ,
appBar: buildSearchField(),
body: searchResultsFuture == null ? buildNoContent() : buildSearchResults(),
);
}
}
class UserResult extends StatelessWidget {
final User eachUser;
UserResult(this.eachUser);
#override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).primaryColor.withOpacity(0.7),
child: Column(children: <Widget>[
GestureDetector(
onTap: ()=> print("tapped"),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.grey,
backgroundImage: CachedNetworkImageProvider(eachUser.url),
),
title: eachUser.profileName != null ? Text(eachUser.profileName,
style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),): 'User',
subtitle: Text(eachUser.username,style: TextStyle(color: Colors.white),),
),
),
Divider(
height: 2.0,
color: Colors.white54,
),
],),
);
}
}

try uploading a more detailed code so as to get insights of what might be wrong.
I thinnk you shoud try to call setSate in
void didChangeDependencies() {
super.didChangeDependencies();
WidgetsBinding.instance.addPostFrameCallback((callback) async {
/// logic here!
eachUser = get data from firebase;
after that call setState();
});
}

I think the proplem is:
Future<QuerySnapshot> users = usersReference.where("profilename",isGreaterThanOrEqualTo: query ).getDocuments();
setState(() {
searchResultsFuture = users;
});
searchResultsFuture get value when users hadn't completed

Related

The argument type 'UserResult' can't be assigned to the parameter type 'UserSearch'

I am trying to make a search functionality that will help a user search for another user. I have created a stateful widget UserSearch and a stateless Widget UserResult. UserSearch builds the results based on UserResult's data. However I am unable to pass UserResult as an argument in UserSearch and I have no clue why. Any help will be great. Thanks in advance
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:vibing_app/feed.dart';
import 'package:vibing_app/model/user.dart';
class UserSearch extends StatefulWidget {
#override
_UserSearchState createState() => _UserSearchState();
}
class _UserSearchState extends State<UserSearch> {
final userRef = FirebaseFirestore.instance.collection('user');
TextEditingController searchController = new TextEditingController();
Future<QuerySnapshot> searchResults;
handleSearch(String query)
{
Future<QuerySnapshot> users = userRef.where("first_name"+ "last_name", isGreaterThanOrEqualTo: query).get();
setState(() {
searchResults = users;
});
}
clearSearch()
{
searchController.clear();
}
AppBar buildSearchField()
{
return AppBar(
backgroundColor: Colors.yellow,
title: TextFormField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search for a user",
filled: true,
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: clearSearch,
),
),
onFieldSubmitted: handleSearch,
),
);
}
Container searchContainer(){
final Orientation orientation = MediaQuery.of(context).orientation;
return Container(
child: Center(
child: ListView(
shrinkWrap: true,
children: [
Text("Find users...",
textAlign: TextAlign.center,
),
],
),
),
);
}
buildSearchResults()
{
return FutureBuilder(
future: searchResults,
builder: (context, snapshot){
if(!snapshot.hasData)
return CircularProgressIndicator();
List<UserSearch> searchResults = [];
snapshot.data.forEach((docu){
AppUser user = AppUser.fromDocument(docu);
UserResult searchResult = UserResult(user);
searchResults.add(UserResult(user)); //This part is giving me the error
});
return ListView(
children: searchResults,
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildSearchField(),
body:
searchResults == null ? searchContainer(): buildSearchResults(),
);
}
}
class UserResult extends StatelessWidget {
final AppUser user;
UserResult(this.user);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
GestureDetector(
onTap: showUserProfile(context,profileID: user.userId),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.yellow,
backgroundImage: Image.network(user.photoURL).image,
),
title: Text(user.firstName + " " + user.lastName),
),
),
Divider(
height: 2.0,
color: Colors.white54,
),
],
),
);
}
}
It is a different types. You need to change List type to UserList:
List<UserResult> searchResults = [];

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.

I got exception caught by widget library error when creating record in firestore

i am working on online notice board project, I used following the code to upload notices uploading is workinging but it gives the following error.
class UploadNotice extends StatefulWidget {
#override
_UploadNoticeState createState() => _UploadNoticeState();
}
class _UploadNoticeState extends State<UploadNotice> {
final _formKey=GlobalKey<FormState>();
final List<String> noticrcategory=
['Exams','Mahapola/Bursary','TimeTables','Results','Other','General'];
File _noticepic;
String title;
String url;
String category;
String dateTime;
var uuid=Uuid();
bool loading = false;
DateTime now=new DateTime.now();
#override
Widget build(BuildContext context) {
Future getImage() async{
var image=await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_noticepic=image;
print('image path: $_noticepic');
});
}
Future uploadPic(BuildContext context)async{
String fileName=basename(_noticepic.path);
final StorageReference firebaseStorageRef=FirebaseStorage()
.ref().child('notices/$fileName');
final StorageUploadTask uploadTask=firebaseStorageRef.putFile(_noticepic);
StorageTaskSnapshot taskSnapshot= await uploadTask.onComplete;
String downloadurl = await taskSnapshot.ref.getDownloadURL();
url=downloadurl.toString();
}
final user = Provider.of<User>(context);
return StreamBuilder(
stream:UserService(uid: user.uid).userData,
builder: (context,snapshot){
User userData=snapshot.data;
String getDepartmentName(){
return userData.department.toString();
}
String department=getDepartmentName();
return loading ? Loading(): Scaffold(
appBar: AppBar(
elevation: 0.0,
title: Text('Notices App',
style: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
backgroundColor: Colors.blue[800],
),
body:SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(child: Text('Add your notice here')
),
),
Container(
child:(_noticepic!=null)?Image.file(_noticepic,fit: BoxFit.fill):
Image.asset('',),
height: 450.0,
width:300.0,
color: Colors.grey[400],
),
Padding(
padding: const EdgeInsets.only(left: 280),
child: Container(
child: IconButton(
icon: Icon(Icons.add_photo_alternate),
color: Colors.grey[700],
iconSize: 40,
onPressed:(){
getImage().then((context){
uploadPic(context);
});
}
),
),
),
TextFormField(
decoration: new InputDecoration(labelText: 'Title'),
validator: (value) {
return value.isEmpty ? 'Title is Required' : null;
},
onChanged: (value) {
setState(() => title = value);
}),
DropdownButtonFormField(
value: category ?? 'General',
items: noticrcategory.map((noticrcategory){
return DropdownMenuItem(
value: noticrcategory,
child: Text('$noticrcategory Category'),
);
}).toList(),
onChanged: (value)=>setState(()=>category=value),
),
Text('${now.day}/${now.month}/${now.year}'),
SizedBox(height: 30.0,),
Container(
height: 30.0,
width: 100.0,
child: RaisedButton(
onPressed: () async {
setState(() => loading=true);
await NoticeService().updteNoticeData(
title,
url,
category,
'unapproved',
now,
'$department',
uuid.v4());
Navigator.of(context).pushReplacementNamed('/Upload Notices');
},
child: Text('Upload',style: TextStyle(color: Colors.white),),
color: Colors.blue[700],
),
)
],
),
),
),
),
);
}
);
}
here is the code in here I can upload notice as image and I can upload the current time to the firestore.
firestore record is created by this code. but it gives the following error.
════════ Exception caught by widgets library ═══════════════════════════════════
The getter 'department' was called on null.
Receiver: null
Tried calling: department
The relevant error-causing widget was
StreamBuilder<User>
lib\…\pages\uploadNotice.dart:56
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by image resource service ════════════════════════════
Unable to load asset:
════════════════════════════════════════════════════════════════════════════════
userData is null, you should do the following:
builder: (context,snapshot){
if(snapshot.hasData){
User userData = snapshot.data;
userData.department.toString();
return Text(userData.department.toString());
else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
}
Since StreamBuilder is asynchronous then first display a loading widget and use hasData to check if any data is returned

Flutter & Firebase: Error with FutureBilder

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().

Value is retrieved only after hot reload in flutter

I'm kinda new to flutter, I've been building a small app using firebase as the backend, whenever I try to load data from firebase I'm not able to fetch the value until I reload the app, this isn't the entire code,
I think the widgets are loading before the data itself, could really use ur help, is there any way that I could use the state to refresh the value?
mycode:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import "package:flutter/material.dart";
import 'package:mine_app/textingpage.dart';
class FriendsPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _FriendsPage();
}
}
class Friends {
final int theirTexts;
final String username;
final int myTexts;
final int totalTexts;
final String friendId;
Friends(this.theirTexts,this.totalTexts,this.username,this.myTexts,this.friendId);
Friends.fromMap(DocumentSnapshot map)
:assert(map["username"]!=null),
assert(map["myTexts"]!=null),
assert(map["theirTexts"]!=null),
assert(map["totalTexts"]!=null),
assert(map["uid"]!=null),
username = map["username"],
myTexts = map["myTexts"],
theirTexts = map["theirTexts"],
totalTexts = map["totalTexts"],
friendId = map["uid"];
}
class _FriendsPage extends State<FriendsPage> {
String user;
String globalid = "";
Future<void> getuser() async {
user = (await FirebaseAuth.instance.currentUser()).uid;
}
#override
void initState() {
getuser();
super.initState();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff723881),
centerTitle: true,
title: Text(
"Chats",
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.people), text: "People"),
Tab(icon: Icon(Icons.search), text: "Find"),
],
indicatorColor: Colors.white,
),
),
body: TabBarView(
children: <Widget>[
Container(
child: snapShotBuilder(context)
),
Container()
],
)),
);
}
Widget snapShotBuilder(BuildContext context){
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("users").document(user).collection("friends").snapshots(),
builder:(context,snapshot){
if (!snapshot.hasData) {
return LinearProgressIndicator();
}
return myListView(context,snapshot.data.documents);
} );
}
Widget myListView(BuildContext context,List<DocumentSnapshot> snapshot){
return Container(
child: ListView(
children: snapshot.map((data)=>myfriends(Friends.fromMap(data))).toList(),
),
);
}
Widget myfriends(Friends friend) {
return Container(
margin: EdgeInsets.only(top: 10.0),
padding: EdgeInsets.all(5.0),
child: ListTile(
onTap:(){
setState(() {
globalid = friend.friendId;
});
print(friend.friendId);
Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatPage(userid:friend.friendId)));
},
trailing: Container(
// margin: EdgeInsets.only(top:30.0,left:10.0,right:0.0),
child: Text(
friend.totalTexts.toString(),),
leading: Container(
width: 60.0,
height: 60.0,
),
title: Text(friend.username,),
),
);
}
}
Yo need to setState() in getUser() and also check if snapshot has data or not also.so the modified code will be
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import "package:flutter/material.dart";
import 'package:mine_app/textingpage.dart';
class FriendsPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _FriendsPage();
}
}
class Friends {
final int theirTexts;
final String username;
final int myTexts;
final int totalTexts;
final String friendId;
Friends(this.theirTexts,this.totalTexts,this.username,this.myTexts,this.friendId);
Friends.fromMap(DocumentSnapshot map)
:assert(map["username"]!=null),
assert(map["myTexts"]!=null),
assert(map["theirTexts"]!=null),
assert(map["totalTexts"]!=null),
assert(map["uid"]!=null),
username = map["username"],
myTexts = map["myTexts"],
theirTexts = map["theirTexts"],
totalTexts = map["totalTexts"],
friendId = map["uid"];
}
class _FriendsPage extends State<FriendsPage> {
String user;
String globalid = "";
Future<void> getuser() async{
setState((){
user = (await FirebaseAuth.instance.currentUser()).uid;
});
}
#override
void initState() {
getuser();
super.initState();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff723881),
centerTitle: true,
title: Text(
"Chats",
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.people), text: "People"),
Tab(icon: Icon(Icons.search), text: "Find"),
],
indicatorColor: Colors.white,
),
),
body: TabBarView(
children: <Widget>[
Container(
child: snapShotBuilder(context)
),
Container()
],
)),
);
}
Widget snapShotBuilder(BuildContext context){
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("users").document(user).collection("friends").snapshots(),
builder:(context,snapshot){
if (snapshot.hasData) {
return myListView(context,snapshot.data.documents);
}else if(snapshot.hasError){
return Center(
child:Text(snapshot.error.toString()));
}else{
return LinearProgressIndicator();
}
} );
}
Widget myListView(BuildContext context,List<DocumentSnapshot> snapshot){
return Container(
child: ListView(
children: snapshot.map((data)=>myfriends(Friends.fromMap(data))).toList(),
),
);
}
Widget myfriends(Friends friend) {
return Container(
margin: EdgeInsets.only(top: 10.0),
padding: EdgeInsets.all(5.0),
child: ListTile(
onTap:(){
setState(() {
globalid = friend.friendId;
});
print(friend.friendId);
Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatPage(userid:friend.friendId)));
},
trailing: Container(
// margin: EdgeInsets.only(top:30.0,left:10.0,right:0.0),
child: Text(
friend.totalTexts.toString(),),
leading: Container(
width: 60.0,
height: 60.0,
),
title: Text(friend.username,),
),
);
}
}
You are right. Widget is built at once after call of initState but you getting user data using Future so it is possilbe that Future is not completed yet. So you just need to wrap your main widget with FutureBuilder:
#override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getUser(), // <-- your future
builder: (context,snapshot) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff723881),
centerTitle: true,
title: Text(
"Chats",
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.people), text: "People"),
Tab(icon: Icon(Icons.search), text: "Find"),
],
indicatorColor: Colors.white,
),
),
body: TabBarView(
children: <Widget>[
Container(
child: snapShotBuilder(context)
),
Container()
],
),
),
),
},
);
}

Resources