How to merge two collections in Firebase flutter application? - firebase

I have created a chat application using flutter and store data in Firebase .Firebase contains two collections .One collection contains user details and another one collection contains user chats with other user.I want to merge two collection details .How to get other user details stored in user collections?
I have attached with screenshots.
Firebase collection
Flutter code

I have the same thing implemented in my Application. What I did is I use the Streambuilder widget twice, one to pull the chats, each and every chat contains a sender_id, which I then use the Id in the second Stream builder to pull user info.
Check the code below.This is all chats page:
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('MyChatHeads')
.doc(_onlineUserId)
.collection('Heads')
.orderBy('head_time', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Scaffold(
body: Center(
child: SpinKitThreeBounce(
color: Colors.black54,
size: 20.0,
),
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Scaffold(
body: placeHolder(),
);
placeHolder();
} else {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => SearchUsersPage(
userId: _onlineUserId,
),
),
);
},
child: Icon(Icons.contacts_rounded),
foregroundColor: Colors.white,
backgroundColor: Color(0xff47c8b0),
),
body: ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot myChatHeads = snapshot.data.documents[index];
return chatHeadItem(
index, myChatHeads, snapshot.data.documents.length);
},
),
);
}
}
},
);
}
The item in all chats page
Widget chatHeadItem(int index, DocumentSnapshot myChatHeads, int length) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Users')
.where('user_id', isEqualTo: myChatHeads['head_subject'])
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: SpinKitThreeBounce(
color: Colors.black54,
size: 20.0,
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Container(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Row(
children: [
CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
child: Image(
height: 56,
width: 56,
image: AssetImage('assets/images/holder.png'),
fit: BoxFit.cover,
),
),
),
SizedBox(
width: 10,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10,
),
Text(
'User not found',
style: GoogleFonts.quicksand(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 16.0,
letterSpacing: .5,
),
),
//setCompanyName(myInterviews),
SizedBox(
height: 4.0,
),
InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => ChatsEngagePage(
userId: _onlineUserId,
secondUserId: myChatHeads['head_subject'],
),
),
);
},
child: Text(
'${myChatHeads['head_last_message']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.quicksand(
color: Colors.black87,
fontSize: 16.0,
letterSpacing: .5,
),
),
),
SizedBox(
height: 10,
),
],
),
),
],
),
),
);
} else {
DocumentSnapshot secondUserInfo = snapshot.data.documents[0];
return Container(
//color: Colors.green,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Column(
children: [
index == 0
? SizedBox(
height: 6,
)
: SizedBox(
height: 0,
),
InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => ChatsEngagePage(
userId: _onlineUserId,
secondUserId: myChatHeads['head_subject'],
userName: secondUserInfo['user_name'],
userImage: secondUserInfo['user_image'],
),
),
);
},
child: Row(
children: [
InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => PublicProfilePage(
userId: _onlineUserId,
secondUserId: secondUserInfo['user_id'],
),
),
);
},
child: CachedNetworkImage(
imageUrl: secondUserInfo['user_image'],
imageBuilder: (context, imageProvider) =>
CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage: imageProvider,
),
),
placeholder: (context, url) => CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage: AssetImage(
'assets/images/holder.png',
),
),
),
errorWidget: (context, url, error) =>
CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage: AssetImage(
'assets/images/holder.png',
),
),
),
),
),
SizedBox(
width: 10,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10,
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text(
'${secondUserInfo['user_name']}',
style: GoogleFonts.quicksand(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 16.0,
letterSpacing: .5,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Text(
timeAgoSinceDateEn(
DateTime.fromMillisecondsSinceEpoch(
myChatHeads['head_time'],
).toString(),
),
//postSnap['press_formatted_date'],
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.grey,
),
),
),
],
),
//setCompanyName(myInterviews),
SizedBox(
height: 4.0,
),
Text(
'${myChatHeads['head_last_message']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.quicksand(
color: Colors.black87,
fontSize: 16.0,
letterSpacing: .5,
),
),
SizedBox(
height: 10,
),
],
),
),
],
),
),
index == length - 1
? Container()
: Divider(
//color: Colors.red,
),
index == length - 1
? SizedBox(
height: 4,
)
: SizedBox(
height: 0,
),
],
),
),
);
}
}
},
);
}
This is a single chat page:
body: Stack(
children: [
Container(
height: double.infinity,
width: double.infinity,
color: Colors.grey[100],
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Chats')
.doc(userId)
.collection(secondUserId)
.orderBy('message_time', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: SpinKitThreeBounce(
color: Colors.black54,
size: 20.0,
),
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Container(
width: MediaQuery.of(context).size.width / 3,
child: Image(
image: AssetImage('assets/images/empty.png'),
width: double.infinity,
),
),
),
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: ListView.builder(
shrinkWrap: true,
reverse: true,
// physics: NeverScrollableScrollPhysics(),
// primary: false,
padding: EdgeInsets.zero,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot myPresses =
snapshot.data.documents[index];
if (myPresses['message_owner'] == userId) {
return Padding(
padding: index == 0
? EdgeInsets.only(bottom: height + 26)
: EdgeInsets.only(bottom: 0),
child: Bubble(
margin: BubbleEdges.only(top: 10),
nip: BubbleNip.rightTop,
alignment: Alignment.topRight,
color: Colors.lightGreen[100],
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
myPresses['message_body'],
style: GoogleFonts.quicksand(
fontSize: 16,
color: Colors.black87,
),
),
Text(
timeAgoSinceDateEn(
DateTime.fromMillisecondsSinceEpoch(
myPresses['message_time'],
).toString(),
),
//postSnap['press_formatted_date'],
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.grey,
),
),
),
],
),
),
);
} else {
return Padding(
padding: index == 0
? EdgeInsets.only(bottom: height + 26)
: EdgeInsets.only(bottom: 0),
child: Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
color: Color(0xffd4eaf5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
myPresses['message_body'],
style: GoogleFonts.quicksand(
fontSize: 16,
color: Colors.black87,
),
),
Text(
timeAgoSinceDateEn(
DateTime.fromMillisecondsSinceEpoch(
myPresses['message_time'],
).toString(),
),
//postSnap['press_formatted_date'],
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.grey,
),
),
),
],
),
),
);
}
},
),
);
}
}
},
),
),
Positioned(
bottom: 10.0,
left: 10.0,
right: 10.0,
child: MeasuredSize(
onChange: (Size size) {
setState(() {
print(size);
height = size.height;
});
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(0),
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.4),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(0, 2), // changes position of shadow
),
],
),
//height: 58,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0, vertical: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: TextFormField(
controller: textEditingController,
keyboardType: TextInputType.multiline,
textCapitalization: TextCapitalization.sentences,
maxLength: 800,
maxLines: null,
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.black54,
letterSpacing: .5,
),
),
decoration: InputDecoration(
labelText: 'Message',
contentPadding: const EdgeInsets.symmetric(
horizontal: 0.0, vertical: 0.0),
errorStyle: TextStyle(color: Colors.brown),
),
onChanged: (val) {
setState(() => _message = val);
},
validator: (val) =>
val.length < 1 ? ('Too short') : null,
),
),
SizedBox(
width: 16,
),
InkWell(
onTap: () {
_submitMessage();
},
child: Padding(
padding:
const EdgeInsets.only(right: 8.0, bottom: 20),
child: Icon(
Icons.send_rounded,
color: Colors.green,
),
),
),
],
),
),
),
),
),
],
),

Related

Rules in cloud firestore has a issue (Flutter) - permission denied

I am building a flutter eCommerce app. if I log in as a new user, with google, or sign up, the home page doesn't load the products... in console, It shows cloud firestore permission denied. then after I close and reopen the app, the page loads with products.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
the above rule is not working. but if I log in, the user logs in successfully, also the user details are added to the DB.
Login page
Error:
W/Firestore( 1298): (22.0.2) [Firestore]: Listen for
Query(target=Query(product order by
name);limitType=LIMIT_TO_FIRST) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient
permissions., cause=null}
HomePage
class _HomeoneState extends State<Homeone> {
final _key = GlobalKey<ScaffoldState>();
ProductServices _productServices = ProductServices();
List _gender = ['Current location', 'loc1', 'loc2'];
String _genderVal;
#override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
final productProvider = Provider.of<ProductProvider>(context);
return Scaffold(
key: _key,
backgroundColor: white,
endDrawer: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
decoration: BoxDecoration(color: red,
borderRadius: BorderRadius.only(bottomRight: Radius.circular(50),bottomLeft: Radius.circular(50)),
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(
'https://blogrope.com/wp-content/uploads/2013/03/happy_wallpaper_by_melaamory-d5n8m53.jpg')),
),
accountName: CustomText(
text: userProvider.userModel?.name ?? "username lading...",
color: black,
weight: FontWeight.bold,
size: 18,
),
accountEmail: CustomText(
text: userProvider.userModel?.email ?? "email loading...",
color: black,
),
),
ListTile(
onTap: () async{
await userProvider.getOrders();
changeScreen(context, OrdersScreen());
},
leading: Icon(Icons.bookmark_outlined,color: Colors.black,),
title: CustomText(text: "My orders"),
),
ListTile(
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => MyHomePage()));
},
leading: Icon(Icons.exit_to_app_outlined,color: Colors.black,),
title: CustomText(text: "Log out"),
),
ListTile(
onTap: () {
userProvider.signOut();
},
leading: Icon(Icons.exit_to_app_outlined,color: Colors.black,),
title: CustomText(text: "Log out"),
),
ListTile(
onTap: () {
AuthService().signOutGoogle();
Navigator.push(
context, MaterialPageRoute(builder: (context) => Login()));
},
leading: Icon(Icons.add),
title: CustomText(text: "Log out for google"),
),
],
),
),
body:
SafeArea(
child: ListView(
physics: AlwaysScrollableScrollPhysics(),
children: <Widget>[
// Custom App bar
Column(
children: <Widget>[
Container(
padding: const EdgeInsets.all(5.0),
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Hi',style: TextStyle(color: Colors.black),)),
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
userProvider.userModel?.name ?? "wait...",
),
),
Container(
margin: EdgeInsets.all(14),
child: Padding(
padding: const EdgeInsets.fromLTRB(200.0,0,0,0),
child: Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: (){
changeScreen(context, CartScreen());
},
child: Icon(Icons.shopping_cart))),
),
),
],
),
),
Container(
margin: EdgeInsets.fromLTRB(280, 0, 0, 0),
child: GestureDetector(
onTap: () {
_key.currentState.openEndDrawer();
},
child: Icon(Icons.menu)),
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Align(
alignment: Alignment.topLeft,
child: Text(
'Delivering to',
style: TextStyle(
color: Colors.grey,
),
),
),
),
Container(
padding: EdgeInsets.all(8),
margin: EdgeInsets.all(4),
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white,
),
child: DropdownButton(
hint: Text('Current location'),
dropdownColor: Colors.white,
value: _genderVal,
isExpanded: true,
onChanged: (value) {
setState(() {
_genderVal = value;
});
},
items: _gender.map((value) {
return DropdownMenuItem(
value: value,
child: Text(value),
);
}).toList(),
),
),
],
),
// Search Text field
// Search(),
Container(
decoration: BoxDecoration(
color: white,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(24),
bottomLeft: Radius.circular(24))),
child: Padding(
padding: const EdgeInsets.only(
top: 5, left: 14, right: 14, bottom: 14),
child: Container(
decoration: BoxDecoration(
color: grey.withOpacity(0.2),
borderRadius: BorderRadius.circular(15),
),
child: ListTile(
leading: Icon(
Icons.search,
color: black,
),
title: TextField(
textInputAction: TextInputAction.search,
onSubmitted: (pattern)async{
await productProvider.search(productName: pattern);
changeScreen(context, ProductSearchScreen());
},
decoration: InputDecoration(
hintText: "Search...",
border: InputBorder.none,
),
),
),
),
),
),
// featured products
ListTile(
title: Text('Menu of the Day',
style: TextStyle(color: Colors.black, fontSize: 18),),
trailing: Text('View all', style: TextStyle(color: Colors.red),
),
),
FeaturedProducts(),
ListTile(
title: Text('Highly rated foods',
style: TextStyle(color: Colors.black, fontSize: 18),),
trailing: Text('View all', style: TextStyle(color: Colors.red),
),
),
FeaturedProductsone(),
// recent products
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(14.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text('Recent products')),
),
],
),
Column(
children: productProvider.products
.map((item) => GestureDetector(
child: ProductCard(
product: item,
),
))
.toList(),
),
],
),
),
);
}
}
Login
final userProvider = Provider.of<UserProvider>(context);
return Scaffold(
key: _key,
body:userProvider.status == Status.Authenticating ? Loading() : Form(
key: _formKey,
child: ListView(
children: <Widget>[
Container(
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.all(30),
child: Center(
child: Text(
'Login',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w500,
),
),
),
),
Container(
child: Center(
child: Text(
'Add details to login',
style: TextStyle(
fontSize: 15,
),
),
),
),
Container(
padding: EdgeInsets.all(20),
child: TextFormField(
controller: _email,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
suffixIcon: Icon(Icons.email),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
hintText: 'Your Email',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
filled: true,
fillColor: Colors.grey[200],
),
validator: (value) {
if (value.isEmpty) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
if (!regex.hasMatch(value))
return 'Please make sure your email address is valid';
else
return null;
}
},
),
),
Container(
padding: EdgeInsets.all(20),
child: TextFormField(
controller: _password,
obscureText: true,
decoration: InputDecoration(
suffixIcon: Icon(Icons.vpn_key_sharp),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
hintText: 'Password',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
filled: true,
fillColor: Colors.grey[200],
),
validator: (value) {
if (value.isEmpty) {
return "The password field cannot be empty";
} else if (value.length < 6) {
return "the password has to be at least 6 characters long";
}
return null;
},
),
),
Container(
padding: EdgeInsets.all(40),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40.0),
),
color: Color(0xfffd44323),
child: Text('Login',
style: TextStyle(
fontSize: 20,
)),
textColor: Colors.white,
onPressed: () async {
// _loginUser(type: LoginType.email,email:_emailController.text, password:_passwordController.text,context: context);
if(_formKey.currentState.validate()){
if(!await userProvider.signIn(_email.text, _password.text))
_key.currentState.showSnackBar(SnackBar(content: Text("Failure")));
return;
}
changeScreenReplacement(context, HomePage());
},
),
),
InkWell(
child: Container(
child: Center(
child: Text(
'Forgot password',
style: TextStyle(
fontSize: 15,
),
),
),
),
onTap: (){
// Navigator.push(
// context, MaterialPageRoute(builder: (context) => Dashone()));
},
),
Container(
margin: EdgeInsets.all(35.0),
child: Center(
child: Text(
'or Login with ',
style: TextStyle(
fontSize: 15,
),
),
),
),
Container(
padding: EdgeInsets.all(5),
margin: EdgeInsets.all(20.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(34)),
color: Color(0xfff3680c1),
),
child: Center(
child: ListTile(
leading: SvgPicture.asset('assets/facebook.svg',
color: Colors.white),
title: Center(
child: Text(
'Login with facebook',
style: TextStyle(
color: Colors.white,
fontSize: 17,
),
)),
),
),
),
Container(
padding: EdgeInsets.all(5),
margin: EdgeInsets.all(20.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(34)),
color: Color(0xfffd44323),
),
child: Center(
child: InkWell(
child: ListTile(
leading: SvgPicture.asset(
'assets/google-plus.svg',
color: Colors.white,
height: 25.0,
width: 25.0,
),
title: Center(
child: InkWell(
child: Container(
child: Text(
'Login with Google',
style: TextStyle(
color: Colors.white,
fontSize: 17,
),
),
),
onTap: () async {
FirebaseAuth _auth = FirebaseAuth.instance;
User user = await AuthService().signInWithGoogle();
print(user);
if (user == null) {
_userServices.createUser({
"name": _auth.currentUser.displayName,
"photo": _auth.currentUser.photoURL,
"email": _auth.currentUser.email,
"uid": _auth.currentUser.uid,
"votes": votes,
"trips": trips,
"rating": rating,
});
// _userServices.createUser(
//
//
// );
// 5s over, navigate to a new page
Navigator.pushReplacement(
context, MaterialPageRoute(
builder: (context) => HomePage()));
}
},
),
)
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: Center(
child: Text(
'Don\'t have an Account?',
style: TextStyle(
fontSize: 15,
),
),
),
),
InkWell(
child: Container(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
'Sign up',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Color(0xfffd44323),
),
),
),
),
onTap: () {
changeScreen(context, SignUp());
},
),
],
),
],
),
),
);
}
}
After restaring the app

How do i reduce the number of firestore reads in flutter

I am building an app that fetches data from firestore using streambuilder.
I have written only 6 documents on firestore but i am getting over 350 reads just for one phone, please how can i reduce this?
Also i saw an article on how to use Cache to reduce the number of reads but that was for Java(Android), I don't know how to use it in flutter.
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection("free")
.where("created", isGreaterThan: DateTime.now().subtract(Duration(hours: 24)))
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text('.....Loading');
}
return ListView.builder(
scrollDirection: Axis.vertical,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot free =
snapshot.data.documents[index];
return Container(
padding: EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(
'${free['safe']['time']}',
style: TextStyle(fontSize: 18),
),
SizedBox(
height: 3,
),
Text(
'${free['safe']['date']}',
style: TextStyle(fontSize: 13),
),
],
),
// SizedBox(width: 20,),
SizedBox(
width:
0.5 * MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'${free['safe']['league']}',
style: TextStyle(fontSize: 15),
),
SizedBox(
height: 2,
),
Text(
'${free['safe']['home']}',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 3,
),
Text(
'vs ${free['safe']['away']}',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 3,
),
Text(
'${free['safe']['tip']}',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.redAccent),
),
],
),
),
// SizedBox(width: 20,),
Column(
children: [
Text(
'${free['safe']['odd']}',
style: TextStyle(fontSize: 18),
),
SizedBox(
height: 4,
),
Builder(
builder: (context) {
if (free['safe']['result'] == 'win') {
return Column(
children: [
Icon(
Icons.check_circle,
color: Colors.green,
),
SizedBox(
height: 8,
),
Text(
'WON',
style: TextStyle(
color: Colors.green,
fontWeight:
FontWeight.bold),
)
],
);
} else if (free['safe']['result'] ==
'loss') {
return Column(
children: [
Icon(
Icons.close,
color: Colors.red,
),
SizedBox(
height: 8,
),
Text(
'LOSS',
style: TextStyle(
color: Colors.red,
fontWeight:
FontWeight.bold),
)
],
);
} else {
return Text('...');
}
},
),
],
),
],
),
);
});
}),

How to display the data from firebase using FutureBuilder in Flutter

Future<List<DocumentSnapshot>> getData() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore
.collection("LiveGames")
.where("Title", isEqualTo: "Solo")
.getDocuments();
return qn.documents;
}
I have extracted the data using this function getData() to use it in the FutureBuilder.
FutureBuilder(
future: getData(),
builder: (_, AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Padding(
padding: const EdgeInsets.only(
top: 50,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Center(
child: SpinKitCircle(
color: Color.fromRGBO(91, 74, 127, 10),
size: 50.0,
),
),
],
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.all(10),
height: 185,
width: double.infinity,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10)),
color: Colors.blueGrey.shade800,
),
height: 150,
width: double.infinity,
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
SizedBox(
height: 6,
),
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Date",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["GameDate"],
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Time",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["GameTime"],
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Map",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["MapName"],
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Mode",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["GameMode"],
style: TextStyle(
color: Colors.white,
)),
],
)
],
),
),
Divider(
color: Colors.white,
),
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Players Joined",
style: TextStyle(
color: Colors.white,
)),
Text(
"${snapshot.data[index].data["RemainingPlayers"]}",
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Winning",
style: TextStyle(
color: Colors.white,
)),
Expanded(
child: FlatButton(
child: Icon(
Icons.arrow_drop_down,
size: 18,
color: Colors.white,
),
onPressed: () {
showModalBottomSheet(
backgroundColor:
Colors.orange
.shade500,
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.only(
topLeft:
Radius.circular(
15),
topRight:
Radius.circular(
15),
)),
context: context,
builder: (context) {
return Container(
child: Column(
children: <Widget>[
],
),
);
},
);
}))
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Remaining Players",
style: TextStyle(
color: Colors.white,
)),
Text(
"${snapshot.data[index].data["TotalSeats"]}",
style: TextStyle(
color: Colors.white,
)),
],
)
],
),
),
Divider(
color: Colors.white,
),
Expanded(
child: Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
Text("Per Kill",
style: TextStyle(
color: Colors.white,
)),
Text(
"₹ ${snapshot.data[index].data["PerKill"]}",
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
Text("Entry Fees",
style: TextStyle(
color: Colors.white,
)),
Text(
"₹ ${snapshot.data[index].data["Entryfees"]}",
style: TextStyle(
color: Colors.white,
)),
],
),
],
),
),
),
],
),
),
Container(
margin: EdgeInsets.only(top: 150),
height: 35,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10)),
color: Colors.orange,
),
child: Padding(
padding: const EdgeInsets.only(left: 125),
child: InkWell(
onTap: () {
print("Solo Joined");
},
child: Text(
"Join Contest",
style: TextStyle(
color: Colors.white,
fontSize: 25,
fontFamily: "OpenSans",
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
],
),
);
});
}
},
),
And then i have displayed some Widgets according to the data.
But in database i have some rank values and i want to display the data in the bottomsheet if the rank from 2 to 10 and 11 to 20 and 21 to 40 are zeros i do not want to display in the bottom sheet only rank1 player i want it to display but if Rank1 player and all the players from rank 1 to 40 some values are there then i have to display the all the data in the bottomSheet
From your question, I don't see any issues on using FutureBuilder in Flutter. The issue here seems to lean more on how you can manage your Firestore data to be displayed.
If you'd like to filter out Players to be displayed base from their Rank. What you can do here is create a Collections for Players where you can sort them by Rank.
Say you'd only like to display Players with Rank 1 in your List.
FirebaseFirestore.instance
.collection('players')
.where('rank', isEqualTo: 1)
.snapshots()
For Rank with ranges, say Ranks 2-10, compound queries can be utilized. For querying in Flutter, you can check the API reference for its equivalence.
FirebaseFirestore.instance
.collection('players')
.where('rank', isGreaterThanOrEqualTo: 2)
.where('rank', isLessThanOrEqualTo: 10)
.snapshots()
Here's a sample that I posted previously that filters and displays all carModels base from the selected carMake. It uses StreamBuilder though. I'm curious on your choice for using FutureBuilder instead of StreamBuilder.
Try the following example:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<QuerySnapshot>(
future: FirebaseFirestore
.instance
.collection('users') // 👈 Your collection name here
.get(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text('Error = ${snapshot.error}');
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['avatar']), // 👈 Your valid data here
);
}).toList());
},
)),
);
}
Also refer: How to use StreamBuilder and FutureBuilder for single and multiple documents

Need to get images from Firebase by using Stream builder in Flutter

I am trying to get images from firebase by using StreamBuilder widget. Tried all what I know but no result. As classes connected with each other tight everything gets tangled. here images are retrieved from manually created list as indicated above but I want to replace them with images from firebase. Please review code and help
class MyApp extends StatefulWidget {
static const String id = 'Myapp_screen';
#override
_MyAppState createState() => new _MyAppState();
}
var cardAspectRatio = 12.0 / 16.0;
var widgetAspectRatio = cardAspectRatio * 1.2;
class _MyAppState extends State<MyApp> {
var currentPage = images.length - 1.0;
#override
Widget build(BuildContext context) {
PageController controller = PageController(initialPage: images.length - 1);
controller.addListener(() {
setState(() {
currentPage = controller.page;
});
});
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xEFEFEF),
Color(0xFFFF),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
tileMode: TileMode.clamp)),
child: Scaffold(
backgroundColor: Colors.transparent,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 12.0, right: 12.0, top: 30.0, bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
CustomIcons.menu,
color: Colors.blue,
size: 30.0,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.search,
color: Colors.blue,
size: 30.0,
),
onPressed: () {},
)
],
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Trending",
style: TextStyle(
color: Colors.blue,
fontSize: 46.0,
fontFamily: "Calibre-Semibold",
letterSpacing: 1.0,
)),
IconButton(
icon: Icon(
CustomIcons.option,
size: 12.0,
color: Colors.white,
),
onPressed: () {},
)
],
),
),
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Row(
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Color(0xFFff6e6e),
borderRadius: BorderRadius.circular(20.0),
),
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 22.0, vertical: 6.0),
child: Text("Animated",
style: TextStyle(color: Colors.white)),
),
),
),
SizedBox(
width: 15.0,
),
Text("25+ Stories",
style: TextStyle(color: Colors.blueAccent))
],
),
),
Stack(
children: <Widget>[
CardScrollWidget(currentPage),
Positioned.fill(
child: PageView.builder(
itemCount: images.length,
controller: controller,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
)
],
),
],
),
),
bottomNavigationBar: NavigationBottomBar(),
),
),
);
}
}
And this is for card scroll
class CardScrollWidget extends StatelessWidget {
var currentPage;
var padding = 20.0;
var verticalInset = 20.0;
CardScrollWidget(this.currentPage);
#override
Widget build(BuildContext context) {
return new AspectRatio(
aspectRatio: widgetAspectRatio,
child: LayoutBuilder(builder: (context, contraints) {
var width = contraints.maxWidth;
var height = contraints.maxHeight;
var safeWidth = width - 2 * padding;
var safeHeight = height - 2 * padding;
var heightOfPrimaryCard = safeHeight;
var widthOfPrimaryCard = heightOfPrimaryCard * cardAspectRatio;
var primaryCardLeft = safeWidth - widthOfPrimaryCard;
var horizontalInset = primaryCardLeft / 2;
List<Widget> cardList = new List();
for (var i = 0; i < images.length; i++) {
var delta = i - currentPage;
bool isOnRight = delta > 0;
var start = padding +
max(
primaryCardLeft -
horizontalInset * -delta * (isOnRight ? 15 : 1),
0.0);
var cardItem = Positioned.directional(
top: padding + verticalInset * max(-delta, 0.0),
bottom: padding + verticalInset * max(-delta, 0.0),
start: start,
textDirection: TextDirection.rtl,
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Container(
decoration: BoxDecoration(color: Colors.white, boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(3.0, 6.0),
blurRadius: 10.0)
]),
child: AspectRatio(
aspectRatio: cardAspectRatio,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Image.asset(images[i], fit: BoxFit.cover),
Align(
alignment: Alignment.bottomLeft,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(
horizontal: 16.0, vertical: 8.0),
child: Text(title[i],
style: TextStyle(
color: Colors.white,
fontSize: 25.0,
fontFamily: "SF-Pro-Text-Regular")),
),
SizedBox(
height: 10.0,
),
Padding(
padding: const EdgeInsets.only(
left: 12.0, bottom: 12.0),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 22.0, vertical: 6.0),
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.circular(20.0)),
child: Text("Read Later",
style: TextStyle(color: Colors.white)),
),
)
],
),
)
],
),
),
),
),
);
cardList.add(cardItem);
}
return Stack(
children: cardList,
);
}),
);
}
}
Manually created list of images
List<String> images = [
"assets/image_04.jpg",
"assets/image_03.jpg",
"assets/image_02.jpg",
"assets/image_01.png",
];
Please add below StreamBuilder Widget code...<br>
StreamBuilder(
stream: Firestore.instance
.collection('details')
.document(documentId)
.collection(collectionId)
.orderBy('timestamp', descending: true)
.limit(20)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<Color>(Colors.green)));
} else {
listMessage = snapshot.data.documents;
return Padding(
padding: const EdgeInsets.only(
top: 5.0, right: 5.0, left: 5.0),
child: ListView.builder(
itemCount: snapshot.data.documents.length,
reverse: true,
itemBuilder: (context, index) =>
buildItem(index, snapshot.data.documents[index]),
),
);
}
},
));
then make one method that return widget which contains layout of your ListView items.
Widget buildItem(int index, DocumentSnapshot document) {
return Container(
child: CachedNetworkImage(
placeholder: (context, url) => Container(
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<Color>(Colors.black),
),
width: 200.0,
height: 200.0,
padding: EdgeInsets.all(70.0),
decoration: BoxDecoration(
color: Colors.lightGreen[200],
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
),
imageUrl: document['imgUrl'],
width: 200.0,
height: 200.0,
fit: BoxFit.cover,
),
}

how to print value from firestore in flutter

how to print value of field.
what I have tried :
print(documents[index].data['Likes.$usersId']);
actually I need this for toggle between icons.
thanks.
Update:
Widget build(BuildContext context) {
return Container(
child: StreamBuilder<QuerySnapshot>(
stream: UserManagement().getPostsStream(),
builder: (_, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
final List<DocumentSnapshot> documents = snapshot.data.documents;
return ListView.builder(
itemCount: documents.length,
itemBuilder: (_, index) {
return Card(
elevation: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0, top: 10),
child: InkWell(
onTap: () => navigateToDetail(
documents[index],
documents[index].data["Userid"],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Row(
children: <Widget>[
Container(
width: 45,
height: 45,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
documents[index].data["User Pic"]),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.all(
Radius.circular(50.5)),
),
),
Padding(
padding: EdgeInsets.only(left: 15),
child: Text(
documents[index].data["Name"],
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18),
),
),
],
),
Padding(
padding: EdgeInsets.only(left: 60, bottom: 10),
child: Text(
DateFormat.yMMMd().add_jm().format(
DateTime.parse(documents[index]
.data["Creation Time"]
.toDate()
.toString())),
style: TextStyle(
color: Colors.black38, fontSize: 12),
),
),
Flexible(
child: Padding(
padding: EdgeInsets.only(left: 75, right: 15),
child: Text(
documents[index].data["Description"],
style: TextStyle(fontSize: 16),
),
),
),
Padding(
padding: EdgeInsets.only(
left: 75, top: 15, bottom: 8),
child: Text(
documents.length.toString() +
"Files uploaded",
style: TextStyle(
color: Colors.blueAccent,
fontSize: 14,
fontStyle: FontStyle.italic),
),
),
Divider(),
new Row(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
print(documents[index].data['Likes.$usersId']);
},
icon: documents[index].data['$usersId'] == true ? Icon(Icons.favorite,
color: Colors.redAccent,
size: 23.0) : Icon(Icons.favorite_border,
color: Colors.redAccent,
size: 23.0)
),
/*Text(documents[index].data['Likes'].length.toString()),*/
],
),
),
Expanded(
child: IconButton(
onPressed: () {
navigateToDetail(documents[index],
documents[index].data["Userid"],);
},
icon: Icon(
Icons.chat_bubble_outline,
color: Colors.blue,
size: 23.0,
),
),
),
Expanded(
child: IconButton(
onPressed: () {},
icon: Icon(
Icons.near_me,
color: Colors.blue,
size: 23.0,
),
),
),
],
),
],
),
),
),
);
});
}
}),
);
}
This is to get Posts :
Stream<QuerySnapshot> getPostsStream() {
return Firestore.instance.collection("Posts").orderBy(
"Creation Time", descending: true).snapshots();
}
Change this:
print(documents[index].data['Likes.$usersId']);
into this:
print(documents[index].data['Likes'][usersId]);

Resources