I am fetching a list using streambuilder from firebase and then compare with another list(Streambuilder) from firebase in flutter. how to compare?
eg: 1 person has 1000 followers and when 2nd person vists 1st person followers it has to show whether the followers(1st person) are also in his(2nd person) list or not.
below image is where i am fetching followers data of another person from firebase. also i have to check whether the followers of another person is in my following list or not.
class FollowersWid extends StatelessWidget {
final String userid;
FollowersWid(this.userid);
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('users/$userid/followers')
.snapshots(),
builder: (context, fetchedData) {
if (fetchedData.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
elevation: 8,
child: ListView.builder(
itemCount: fetchedData.data.docs.length,
itemBuilder: (ctx, index) => Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
UnFollow(fetchedData.data.docs[index]['username'], userid)
],
),
));
}
},
);
}
}
For this you can use .where and .contains eg.
List firebaseList1 = [0, 5, 1];
List firebaseList2 = [1, 0, 2];
print(firebaseList1.where((item) => firebaseList2.contains(item)));
//output: (0,1)
Related
I am trying to get only the groups to which the user belongs, but with the current code I show all the existing groups.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("My groups"),
automaticallyImplyLeading: false,
),
body: StreamBuilder(
stream: userColeccion.doc('$userID').collection("grupos").snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: [
Text("groups users"),
Expanded(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("grupos")
.snapshots(),
builder: (context, groupSnapshot) {
if (groupSnapshot.hasData) {
var groupList = (groupSnapshot.data
as QuerySnapshot<Map<String, dynamic>>)
.docs
.map((d) => Group.fromJson(d.data()))
.toList();
return ListView.builder(
itemCount: groupList.length,
itemBuilder: (context, index) {
var group = groupList[index];
return Card(
child: ListTile(
title: Text(group.namegroup),
),
);
},
);
}
return const Center(child: CircularProgressIndicator());
},
),
),
],
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
when entering "users", you can enter the id of each one, within that id there is a collection called "groups" which stores the key of the different groups to which the user belongs, with this key I intend to search in the "groups" collection that is at the "users" level, but it stores the key of the groups that exist.
collection "usuarios"
collection "grupos"
In short, I would like to show on the screen only the groups to which the user belongs, the keys are stored by the user, thank you very much for any help or explanation.
To get the documents from grupos where namegroup is equal to Grupo 2, you can use a query:
stream: userColeccion.doc('$userID').collection("grupos")
.where("namegroup", "==", "Grupo 2")
.snapshots(),
'Uid', isEqualTo:FirebaseAuth.instance.currentUser!.uid... in the fields also add the uid of the current so it should checking
I am trying to display a bannerAd between every 3 posts. But ads do not show. I presume, that the list could be empty, as this list is a list build from the posts user likes and saves.
#override
Widget build(BuildContext context) {
return Expanded(
child: ListView(
padding: EdgeInsets.symmetric(horizontal: 10.0),
children: [
StreamBuilderWrapper(
shrinkWrap: true,
stream: postRef
.where("bookmarks",
arrayContains: FirebaseAuth.instance.currentUser.uid)
.orderBy('timestamp', descending: true)
.snapshots(),
physics: NeverScrollableScrollPhysics(),
itemBuilder: (_, DocumentSnapshot snapshot) {
internetChecker(context);
Review posts = Review.fromJson(snapshot.data());
return Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: Posts(post: posts),
);
},
),
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (context, index) {
return Column(
children: [
if (index % 3 == 0 && index != 0)
AdWidget(ad: ad)
],);})
]));
}
This is my first time working with flutter, and i am new to coding. I am trying to display the bannerAds, however, they do not show and no log is displayed. This is probably due to the render error I have:
The following _CastError was thrown during paint():
Null check operator used on a null value
The relevant error-causing widget was:
ListView
When the exception was thrown, this was the stack:
#0 RenderViewportBase._paintContents
(package:flutter/src/rendering/viewport.dart:653:25)
#1 RenderViewportBase.paint
(package:flutter/src/rendering/viewport.dart:645:7)
#2 RenderObject._paintWithContext
(package:flutter/src/rendering/object.dart:2317:7)
#3 PaintingContext._repaintCompositedChild
(package:flutter/src/rendering/object.dart:139:11)
#4 PaintingContext.repaintCompositedChild
(package:flutter/src/rendering/object.dart:100:5)
...
The following RenderObject was being processed when the exception was
fired:
RenderViewport#ae00e
... needs compositing
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=360.0, h=507.0)
... layer: OffsetLayer#0dfc7 DETACHED
... engine layer: Null#007db
... offset: Offset(0.0, 0.0)
... size: Size(360.0, 507.0)
... axisDirection: down
... crossAxisDirection: right
... offset: ScrollPositionWithSingleContext#1c5d2(offset: 0.0, range:
null..null, viewport: 507.0, ScrollableState,
AlwaysScrollableScrollPhysics
-> ClampingScrollPhysics -> RangeMaintainingScrollPhysics,
IdleScrollActivity#40f4c, ScrollDirection.idle)
I am confused with the widgets and views. Help me, please! Thank you!
i didn't understand clearly what you re doing, i assume you re doing this wrong way,I edited the whole code this may help .
#override
Widget build(BuildContext context) {
return Expanded(
child: StreamBuilder(
stream: postRef
.where("bookmarks",
arrayContains: FirebaseAuth.instance.currentUser!.uid)
.orderBy('timestamp', descending: true)
.snapshots(),
builder: (_, DocumentSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.separated(itemCount: snapshot.data.docs.length,
itemBuilder: (
context,
index,
) {
internetChecker(context);
Review posts = Review.fromJson(snapshot.data());
return Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: Posts(post: posts),
);
}, separatorBuilder: (context, index) {
if (index % 3 == 0 && index != 0)
return
AdWidget(ad: ad);
}, );
}else if (snapshot.hasError) {
return Center(
child: Text("error"),
);
} else {
return Center(
child: Text("loading"),
);
}
},
),);
I my app user are going to create by TextForm Field a collection into FIrestore and this collection has some documents.
Into my StreamBuilder I have set up stream and I can get the documents but I cant retrieve the Number of the documents created by the user logged with snapshot.data.lenght which I get the error:
Class 'DocumentSnapshot' has no instance getter 'lenght'.
Receiver: Instance of 'DocumentSnapshot'
Tried calling: lenght
The code:
class CollectData extends StatefulWidget {
#override
_CollectDataState createState() => _CollectDataState();
}
class _CollectDataState extends State<CollectData> {
final String phone;
final String wife;
final String location;
_CollectDataState({this.phone, this.wife, this.location,});
Stream<DocumentSnapshot> getDatabase() async* {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
yield* Firestore.instance
.collection('dataCollection')
.document(user.uid)
.snapshots();
}
#override
Widget build(BuildContext context,) {
return StreamBuilder(
stream: getDatabase(),
builder: (context, snapshot,) {
if (snapshot.data != null) {
return Column(
children: <Widget>[
Container(
height: 500,
child: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.lenght,
itemBuilder: (BuildContext context, int) {
return Card(
color: Color(0xFF1f2032),
elevation: 15,
child: Container(
width: 60,
height: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Card(
color: Color(0xfffeaf0d),
child: Container(
height: 40,
width: 40,
child: Icon(
Icons.contacts,
color: Colors.white,
size: 25,
)),
),
Text(
snapshot.data['phone'],
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
),
),
);
},
),
),
],
);
} else
return NoData();
},
);
}
}
A lot of things have changed in the newest version of Flutter and Firebase.
Where you call the StreamBuilder you have to pass in the QuerySnapshot type like this:
return StreamBuilder<QuerySnapshot>(...
And change your itemCount line to:
itemCount: streamSnapshot.data!.docs.length,
That should solve the problem for you.
DocumentSnapshot doesn't have any length property because, when you are doing this:
Stream<DocumentSnapshot> getDatabase() async* {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
yield* Firestore.instance
.collection('dataCollection')
.document(user.uid)
.snapshots();
}
It means you are only retrieving 1 document, since each document id is unique then the above will give you only one document.
You can add here:
itemCount: 1
If you want a list of documents then you have to do the following:
Stream<QuerySnapshot> getDatabase() async* {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
yield* Firestore.instance
.collection('dataCollection')
.snapshots();
}
and then in itemCount:
itemCount: snapshot.data.documents.length
there seems to be typo in lenght, you meant length, right?
your error message clearly complaining about typo
Class 'DocumentSnapshot' has no instance getter 'lenght'.
plz just try replacing this line itemCount: snapshot.data.lenght, with itemCount: snapshot.data.length,
I created a ListView that populates from a Firebase collection by using a StreamBuilder widget. It takes some time for the ListView to populate because I'm running tasks (HTTP requests) for each item of the Firebase collection and then displaying the result in the list.
When I navigate away from the page with the ListView and then return to the page (using PageView), the ListView appears to refresh entirely instead of using the last seen version. So there is a ~5 second circular progress indicator while the list re-populates every time the page is re-opened.
Questions:
What is the best way to make this ListView not complete a full 5
second refresh every time the page is re-opened? Can it use the last seen version and only update when items are added to the firebase collection?
If I were to remove the tasks (HTTP requests) that need to be ran on each item of the collection and instead simply show values directly from the Firebase collection, should the refresh time be fast enough that it is not a problem?
Is it best to create a local database (using sqflite) that syncs with the Firebase collection to prevent slow refreshes?
Code:
class AccountsPage extends StatefulWidget {
#override
_AccountsPageState createState() => _AccountsPageState();
}
class _AccountsPageState extends State<AccountsPage> {
User user;
Widget _buildListItem(BuildContext context, DocumentSnapshot document, String uuid) {
// get data from firebase
String token = document.data.values.toList()[0];
// For current document/token, make an HTTP request using the token and return relevant data
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: FutureBuilder(
future: anHTTPrequest(token, uuid),
builder: (context, projectSnap) {
if (projectSnap.connectionState == ConnectionState.none ||
!projectSnap.hasData || projectSnap.data.length == 0) {
return Container();
}
return ListView.builder(
shrinkWrap: true,
itemCount: projectSnap.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(projectSnap.data[index]),
);
},
);
},
),
)],
);
}
#override
Widget build(BuildContext context) {
final container = StateContainer.of(context);
user = container.user;
return Container(
child: Scaffold(
body: Column(
children: <Widget>[
new Flexible(
child: StreamBuilder(
stream: Provider.of(context).collectionRef.document(user.uuid).collection('tokens').snapshots(),
builder: (context, snapshot){
if (!snapshot.hasData){
return Container(
child: Center(
child: Text("No data")
)
);
}
return ListView.builder(
padding: EdgeInsets.all(8.0),
reverse: false,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, int index) {
return _buildListItem(context, snapshot.data.documents[index], user.uuid);
}
);
}
)
),
]
),
),
);
}
}
Coming from Firestore, I am a little bit struggling how to receive data from Firebase real time database. I just want a nice grid view of images which are loaded from the realtime database.
Error: flutter: The following NoSuchMethodError was thrown building:
flutter: Class 'DataSnapshot' has no instance method '[]'.
flutter: Receiver: Instance of 'DataSnapshot'
I guess it's index related. No idea how to correctly map it within a list.
import 'package:cached_network_image/cached_network_image.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(16.0),
child: new FutureBuilder(
future: FirebaseDatabase.instance
.reference()
.child('messages')
.child('1551276762582')
.orderByChild('messagetype')
.equalTo('1')
.once(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data != null) {
return new Column(
children: <Widget>[
new Expanded(
child: new GridView.builder(
// itemCount: item.length,
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemBuilder: (context, index) {
return GridTile(
child: CachedNetworkImage(
imageUrl: snapshot.data[index]['imageUrl']
.toString()));
},
),
)
],
);
} else {
return new CircularProgressIndicator();
}
} else {
return new CircularProgressIndicator();
}
}));
}
}
I could solve it with the following code. Again, I have to say that the Firebase documentation really lacks, which is quite disappointing, since Firebase is a great tool. Moreover, I do not understand, that there is no documentation on 'How to use Firebase with Flutter' (we are talking about both Google products.) Notwithstanding, here is the working code for anyone, who likes to use Streambuilder with Gridview.builder with the Realtime Database in Flutter:
StreamBuilder(
stream: FirebaseDatabase.instance
.reference()
.child('messages')
.child(groupId)
.orderByChild('messagetype')
.equalTo(1)
.onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.snapshot.value != null) {
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
List<dynamic> list = map.values.toList()
..sort(
(a, b) => b['timestamp'].compareTo(a['timestamp']));
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemCount: list.length,
padding: EdgeInsets.all(2.0),
itemBuilder: (BuildContext context, int index) {
return Container(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen(
imageUrl: list[index]["imageUrl"])),
);
},
child: CachedNetworkImage(
imageUrl: list[index]["imageUrl"],
fit: BoxFit.cover,
),
),
padding: EdgeInsets.all(2.0),
);
},
);
} else {
return Container(
child: Center(
child: Text(
'Es wurden noch keine Fotos im Chat gepostet.',
style: TextStyle(fontSize: 20.0, color: Colors.grey),
textAlign: TextAlign.center,
)));
}
} else {
return CircularProgressIndicator();
}
})),
Something that I do that helps me solve issues, is by explicitly turning snapshots into Maps the following way.
Map yourModel = Map.from(datasnapshot);
also many times when handling null data or so on I have to turn the asyncSnap value that comes from the future Builder into a Datasnapshot from firebase in the following way
Datasnapshot snap = asyncSnap.data;
then handle for snap being null
if(snap.value!=null){}
Hope this helps! if you need help send me a message