flutter application streambuilder in real time
this is group chat app
I need to get bool chat vale from firebase firestore if true or false in real time without exit page and re open to update the value Or any way to prevent the user from sending a message in the group when the value of Chat is equal to False
this is my code
StreamBuilder(builder: (context, snapshot) {
if(chat == false){
return Container(
child:
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30,vertical: 5),
child: Row(
children: [
Image.network('https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Error.svg/1200px-Error.svg.png',height: 25,width: 25,),
SizedBox(width: 20,),
Expanded(child: Text('Only admin can send message',style: TextStyle(fontSize: 10),maxLines: 1,overflow: TextOverflow.ellipsis,))
],
),
)
);
}else{
return Padding(
padding: const EdgeInsets.all(10.0),
child: Material(
borderRadius: BorderRadius.circular(50),
color: ColorConstants.appColor,
child: Padding(
padding: const EdgeInsets.only(bottom: 4.0,top: 4.0,left: 1.5,right: 1.5),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50)
),
child:
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: TextField(
controller: messageedit,
onChanged: (value){
messageText = value;
},
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(
vertical: 10,
horizontal: 20
),
hintText: 'Write your message .... ',
border: InputBorder.none
),
)),
IconButton(onPressed: () {
messageedit.clear();
_firestore.collection("messages").add({
'text': messageText,
'sender' : email,
'time' : FieldValue.serverTimestamp(),
}).whenComplete(() => sendNotification('$messageText', '$email'));
}, icon: Icon(Icons.send_rounded,color: ColorConstants.appColor,))
],
)
),
),
),
);
}
},stream: _firestore.collection('admin').doc('admin').snapshots(),),
your code has the wrong implementation.
when providing the doc it should be the docId ({DOCID}) on firestore
e.g.: _firestore.collection('admin').doc({DOCID}).snapshots()
i don't get how do you create the chat variable
i don't see anywhere in the code where do you process snapshot data from firestore
check the flutter fire documentation for the correct implementation
Related
can anyone find the error in this I cannot fetch the category from firebase to flutter dropdown?
this is my code
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Select Category', style: boldTextStyle(size: 18)),
8.height,
Container(
width: context.width() * 0.45,
decoration: BoxDecoration(
borderRadius: radius(), color: Colors.grey.shade200),
padding:
EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: DropdownButton(
underline: Offstage(),
items: categories.map((e) {
return DropdownMenuItem(
child: Text(e.name.validate()), value: e);
}).toList(),
isExpanded: true,
value: selectedCategory,
onChanged: (dynamic c) {
selectedCategory = c;
setState(() {});
},
),
),
],
),
I cannot display the data from firebase to dropdown after getting the data
I have a widget where I use the provider but where I want to use the values is in normal widgets so maybe anyone can help.
This is where I use the provider :
Widget _buildName(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Full Name',
style: kLabelStyle3,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
height: 50.0,
child: TextFormField(
initialValue: UserData.fullname;
validator: (val) => val.isEmpty ? 'Enter your Name' : null,
onChanged: (val) {
setState(() => _currentfullname = val);
},
style: TextStyle(
color: Colors.black,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: Colors.black,
width: 2.0,
),
),
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.person,
color: Colors.black,
),
hintText: 'Enter your Name',
hintStyle: kHintTextStyle2,
),
),
),
],
);
}
#override
Widget build(BuildContext context) {
final user = Provider.of<Userr>(context);
return StreamBuilder<UserData>(
stream: DatbaseService(uid:user.uid).userData,
builder: (context, snapshot) {
if(snapshot.hasData){
UserData userData =snapshot.data;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Form(
key: _formKey,
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(
horizontal: 40.0,
vertical: 10,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Stack(
children: [
Container(
width: 110,
height: 110,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"https://images.pexels.com/photos/3307758/pexels-photo-3307758.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=250",
))),
),
Positioned(
bottom: 0,
right: 0,
child: Container(
height: 35,
width: 35,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
width: 4,
color: Theme.of(context)
.scaffoldBackgroundColor,
),
color: Colors.green,
),
child: Icon(
Icons.edit,
color: Colors.white,
),
)),
],
),
),
SizedBox(
height: 10,
),
Text(
'Mein Profil',
style: TextStyle(
color: Colors.black,
fontFamily: 'OpenSans',
fontSize: 20.0,
fontWeight: FontWeight.w600,
),
),
showAlert2(),
_buildEmailTF(),
SizedBox(
height: 30.0,
),
_buildName(),
SizedBox(
height: 30.0,
),
_builduserName(),
SizedBox(
height: 30.0,
),
_buildPasswordTF(),
SizedBox(height: 30,),
_buildPassword2TF(),
_buildUpdateDataButton(),
// _buildEmailform(),
],
),
),
)
],
),
),
),
),
);
}else{
return null;
}
}
);
}
}
class DatbaseService{
final String uid;
DatbaseService({this.uid});
//collection reference
final CollectionReference myprofilsettings = FirebaseFirestore.instance.collection('meinprofilsettings');
Future updateUserData(String user,String fullname,String password,String email)async{
return await myprofilsettings.doc(uid).set({
'username':user,
'fullname':fullname,
'passwort':password,
'email':email,
});
}
//profil list from snapshot
List<myprofil> _myprofillistFromSnapshot(QuerySnapshot snapshot){
return snapshot.docs.map((doc){
return myprofil(
user: doc.data()['user']??'',
fullname: doc.data()['fullname']??'',
email: doc.data()['email']??'',
passowrd: doc.data()['password']??'',
);
}).toList();
}
//userData from snapshot
UserData _userDataFromSnapshot(DocumentSnapshot snapshot){
return UserData(
uid: uid,
name: snapshot.data()['name'],
fullname: snapshot.data()['fullname'],
email: snapshot.data()['email'],
password: snapshot.data()['password'],
);
}
//get myprofilsettings stream
Stream<List<myprofil>> get settings{
return myprofilsettings.snapshots().map(_myprofillistFromSnapshot);
}
//get user doc stream
Stream<UserData> get userData{
return myprofilsettings.doc(uid).snapshots().map(_userDataFromSnapshot);
}
}
import 'package:flutter/cupertino.dart';
class Userr{
final String uid;
Userr({this.uid});
}
class UserData {
final String uid;
final String user;
final String fullname;
final String email;
final String passowrd;
UserData({this.uid,this.user,this.fullname,this.email,this.passowrd, name, password});
Ignore this:
Because flutter says __it looks like It looks like your post is mostly code; please add some more details. ___
IM adding some textdehpkfnwrfemrjfikerfoiwnfdoiwjefiojnweoidfjwiodjwiojdoijweiodjweiojdoiewjdijewoijdoejwdiojewiojdiowjedijweoidjiowediwjdoiwejdiowjdiojwoidjaldknjlncjnnc xy,,y,y,,y,ykampkdnndendiowendiojweiopjdipqejkdpojkdposkqwpodkqopwkdopkqwopdskqopdkpoqwkdopqkwopdkqwpodkpoqkdpkqpodkpqkdpokdpo<skcpoaskdpoakdopkdpoekwopdkwepokdpowekdpokwepodkwepokdpowekdpowekpdkpekdpokeopdkpekdpowekdopewkpdkwpekdpwekdpowekdpowekdpowekdpkwepodkwepodkpoekdpoewkdpoekdp
======== Exception caught by widgets library =======================================================
The following assertion was thrown building StreamBuilder<UserData>(dirty, state: _StreamBuilderBaseState<UserData, AsyncSnapshot<UserData>>#c612d):
A build function returned null.
The offending widget is: StreamBuilder<UserData>
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:
StreamBuilder<UserData> file:///Users/name/StudioProjects/project/lib/seitenleiste/meinacount.dart:356:16
When the exception was thrown, this was the stack:
#0 debugWidgetBuilderValue.<anonymous closure> (package:flutter/src/widgets/debug.dart:305:7)
#1 debugWidgetBuilderValue (package:flutter/src/widgets/debug.dart:326:4)
#2 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4592:7)
#3 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4759:11)
#4 Element.rebuild (package:flutter/src/widgets/framework.dart:4281:5)
...
====================================================================================================
I’m assuming that your _buildName() is a method of your widget and that you call it from you build method somewhere.
This means that you can pass either the context or the user into this method:
_buildName(BuildContext context) {} or _buildName(User user) {}
Try providing more of the code next time, specifically the parts where you call the method.
Edit after post update:
You need to have the user object in the buildName method so you cannot simply do UserData.fullname because UserData is a class not an instance.
So to get your data in the buildName you need to change it to:
_buildName(UserData userData) {
userData.fullname; // this now exists
}
And call is like: _buildName(userData)
this is my users collection in cloud fire store:
users collection
this is the function that gets users from users collection in firestore
Stream<QuerySnapshot> fetchUsersInSearch() {
return Firestore.instance.collection('users').snapshots();
}
i use this method
final emailResults = snapshot.data.documents
.where((u) => u['email'].contains(query));
in the following streamBuilder to fetch users by their email.
i have this streamBuilder to populate the data on screen
return StreamBuilder<QuerySnapshot>(
stream: DatabaseService().fetchUsersInSearch(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
final emailResults = snapshot.data.documents
.where((u) => u['email'].contains(query));
if (!snapshot.hasData) {
return Container(
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
'',
style: TextStyle(
fontSize: 16, color: Theme.of(context).primaryColor),
),
),
);
}
if (emailResults.length > 0) {
return Container(
color: Theme.of(context).primaryColor,
child: ListView(
children: emailResults
.map<Widget>((u) => GestureDetector(
child: Padding(
padding: const EdgeInsets.all(0.1),
child: Container(
padding: EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
border: Border(
bottom: BorderSide(
width: 0.3, color: Colors.grey[50]))),
child: ListTile(
leading: CircleAvatar(
backgroundColor:
Theme.of(context).primaryColor,
backgroundImage:
NetworkImage(u['userAvatarUrl']),
radius: 20,
),
title: Container(
padding: EdgeInsets.only(left: 10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(u['email'],
style: TextStyle(
fontSize: 16,
color: Theme.of(context)
.accentColor),
overflow: TextOverflow.ellipsis),
SizedBox(
height: 5,
),
],
),
),
),
),
),
onTap: () {
showUserProfile(u['id']);
},
))
.toList(),
),
);
} else {
return Container(
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
'No results found',
style: TextStyle(
fontSize: 16,
color: Theme.of(context).accentColor,
),
),
),
);
}
});
this is working perfectly and fetching users inside a listView by their email...
p.s: the (query) is a string i type in a seach bar.
how can i make a query to fetch users by their otherUsernames...the second field in the screenshot of the users collection ?!
i tried this:
final otherUsernamesResults = snapshot.data.documents
.where((u) => u['otherUsernames'].contains(query));
but its returning this error:
The method 'contains' was called on null.
Receiver: null
Tried calling: contains("#username1")
what am i doing wrong here ?!!
any help would be much appreciated..
Try this:-
Stream<QuerySnapshot> getUsers() {
final usersCollection = FirebaseFirestore.instance.collection('users');
return usersCollection.where('otherUsernames', arrayContainsAny: ['username1', 'username2']);
}
For firestore version 0.16.0
The issue here is that when I fetch the data, I am suppose to fetch it for the current user but it is rather fetching data for all users within that collection.
I have done reading and watched a number of videos for a possible solution but I can't seem to find how to do this. Your help is needed please. Thanks.
A excerpt of the bode is below.
File image;
TextEditingController loginNameController = TextEditingController();
TextEditingController loginPhoneController = TextEditingController();
TextEditingController loginAddressController = TextEditingController();
clearForm() {
setState(() {
image = null;
loginNameController.clear();
loginPhoneController.clear();
loginAddressController.clear();
});
}
//=====> FOR INSTANCES OF FIREBASE <=====
final auth = FirebaseAuth.instance;
final db = FirebaseFirestore.instance;
User user = FirebaseAuth.instance.currentUser;
body: Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: StreamBuilder(
stream: db.collection("collection name").snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if (!snapshot.hasData) {
return Center(
child: spinkit,
);
}
return ListView.builder (
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index){
return Stack(
children: [
Column(
children: [
Stack(
children: [
// ===> RETRIEVING USER DETAILS AND SHOWING IT IN A ROW <===
Container(
padding : EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CircleAvatar(
backgroundColor: Palette.mainColor,
radius: 50,
child: ClipOval(
child: SizedBox(
height: 150,
width: 150,
child: image == null ? Center(
// child: Image.asset("asset/images/placeholder.png", fit: BoxFit.cover,),
child: Image.network(snapshot.data.documents[index].get("image")),
):
Image.file(image, fit: BoxFit.cover,),
),
),
),
SizedBox(width: 16,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 0),
child: Text(snapshot.data.documents[index].get("Name"),
style: TextStyle(
letterSpacing: 2,
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
),),
),
SizedBox(height: 5,),
Text(snapshot.data.documents[index].get("Address"),
style: TextStyle(
letterSpacing: 2,
color: Colors.black54,
fontSize: 16,
),),
SizedBox(height: 5,),
Text(snapshot.data.documents[index].get("Number"),
style: TextStyle(
letterSpacing: 2,
color: Colors.black54,
fontSize: 16,
),),
],
),
),
Padding(
padding: EdgeInsets.only(left: 0, bottom: 15),
child: IconButton(
icon:Icon(Icons.edit, color: Palette.mainColor, ),
onPressed: () { },
),
),
],
),
),
],
),
],
),
],
);
},
);
},
),
)
The collection name is members
Try like this, stream of your widget should be like this, as said above.
db.collection("Users").document(user.uid).snapshots();
for length in Listview.builder, change it too
snapshot.data.length;
And last, All the data which you fetch data like this should change into
from:
snapshot.data.documents[index].get("image")
To:
snapshot.data["image"]
Note I didn't test it. So, it might or might not work.
First of All use a DocumentSnapshot Shown below:
StreamBuilder<DocumentSnapshot>
Make a collection to get current user Profile data.
db.collection("Users").doc(user.uid).snapshots();
Remove ListView.builder
To get an Email Address use the below Line
Text('${streamSnapshot.data['Email Address']}'),
Here is the complete Article https://medium.com/#kamranktk807/fetch-user-data-from-firestore-and-show-them-in-profile-screen-using-flutter-609d2533e703
By the way I sol this problem with the help of a Professional Flutter Developer SHAKIR ZAHID [shakirzahid191#gmail.com].
I have a stream connected to a Firebase document and I am constantly listening to any changes of the document.
I want to update some parts of my app when document is changed so I made the stream globally available and I use StreamBuilders on different screens so the latest data will be available ob the screen.
Will there be a problem with the global stream and multiple StreamBuilders? How does the app work when the StreamBuilders are created on multiple screens?
This is my global stream:
Stream userDocGlobalStream =
Firestore.instance.collection("user").document(CurrentUserDetails.id).snapshots();
This is the build method of one of my screens widget (I change the color of a button depending on the stream data):
#override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
return StreamBuilder(
stream: userDocGlobalStream,
builder: (context, snapShot) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
side: BorderSide(color: theme.primaryColor)),
elevation: 30,
child: Container(
margin: EdgeInsets.all(10),
child: Column(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment
.stretch, //need to use it to strech the items horizontally
children: <Widget>[
Container(
//to think, it is used for the background color of the picture. can undo it later
decoration: BoxDecoration(
color: theme.primaryColor.withAlpha(10),
borderRadius: BorderRadius.circular(10),
),
padding: EdgeInsets.all(10),
child: GestureDetector(
onTap: () {}, //go to user profile when pressed.
child: CircleAvatar(
radius: 70,
backgroundImage: NetworkImage(userImageUrl),
),
),
),
],
),
Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: FittedBox(
child: Text(
"Username : $username ",
),
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: FittedBox(
child: Text(
"interests : ${interests.toString().replaceAll("[", "").replaceAll("]", "")} ",
),
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: FittedBox(
child: Text("Distance from you : $distanceFromUser KM"),
),
), //to do address and km from you should go here
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
color: theme.primaryColor,
icon: Icon(Icons.chat),
onPressed: () {}, //send a message to the user
),
IconButton(
color: Colors.cyan,
icon: CurrentUserDetails.friendRequestsSent.contains(
userId) //to do=> THE ICON MUST CHANGE WITH EVERY CHANGE OF THE DATA
? Icon(
Icons.person,
color: Colors.black,
)
: CurrentUserDetails.friends.contains(userId)
? Icon(
Icons.person,
color: Colors.green,
)
: Icon(Icons.person_add),
onPressed: () {
try {
//to do
CurrentUserDetails.friendRequestsSent
.contains(userId)
? DoNothingAction()
//Cancel the sent request:
: CurrentUserDetails.friendRequestsReceived
.contains(userId)
? DoNothingAction()
//accept friend request:
: CurrentUserDetails.friends
.contains(userId)
? DoNothingAction()
//delete the friend:
: DatabaseManagement().sendFriendRequest(
CurrentUserDetails.id,
userId); //userId is the id of the user we are showing the widget for
} catch (e) {
showDialog(
context: context,
builder: (ctx) => DialogueWidget(
titleText: "Error occured",
contentText:
e.toString(), //to do+> change the er
),
);
}
} //send friend request when this button is pressed
),
IconButton(
color: Colors.red[300],
icon: Icon(Icons.location_on),
onPressed:
() {}, //show a map with a users location details on it.
)
],
)
],
),
),
);
},
);
}
}
StreamBuilder automatically starts and ends listening of provided stream:, so there will be no problem when using one broadcast stream in multiple places around the app. Even nested listening to one stream is not an issue.
Here are some helpful links if you want to dig deeper:
https://dart.dev/tutorials/language/streams
https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html