NoSuchMethodError: Class 'QuerySnapshot' has no instance method '[]' - firebase

Im trying to get posts(images) for every user.User's id are stored in posts collection and every userid document will have a subcollection will contains all posts document.but im getting this error.
The following NoSuchMethodError was thrown building:
Class 'QuerySnapshot' has no instance method '[]'.
Receiver: Instance of 'QuerySnapshot'
Tried calling: []("mediaUrl")
this is the code.
getPost(){
return FutureBuilder(
future: Firestore.instance.collection('posts').document(user.id
).collection('userPosts').getDocuments(),
// ignore: missing_return
builder: (context,snapshot) {
if (snapshot.hasData) {
return
Container(
height: 200,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
child: Image.network(snapshot.data["mediaUrl"],)
);
}
),
],
),
);
}
if (!snapshot.data ) {
return Text('No posts');
} else {
return CircularProgressIndicator();
}
}
);
}`

If your media url is inside a document then try this :
Image.network(snapshot.data.documents[index]["mediaUrl"],)
Full code with another approach :
getPost(){
return FutureBuilder(
future: Firestore.instance.collection('posts').document(user.id
).collection('userPosts').getDocuments(),
// ignore: missing_return
builder: (context,snapshot) {
if (snapshot.hasData) {
return
Container(
height: 200,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot docSnapshot = snapshot.data.documents[index];
return Image.network(docSnapshot["mediaUrl"],)
);
}
),
],
),
);
}
if (!snapshot.data ) {
return Text('No posts');
} else {
return CircularProgressIndicator();
}
}
);
}

Related

How to create streambuilder and listview with Firebase Realtime database data (Flutter chat app)

I'm building a flutter chat app for my personal learning project where the data will be retrieved from Firebase Realtime database.
I got this code from a tutorial but it is showing errors. How to solve this?
StreamBuilder(
stream: dbRef.onValue,
builder: (context, snapshot) {
if (snapshot.hasData) {
print("Error on the way");
messages.clear();
DataSnapshot dataValues = snapshot.data.snapshot; //Error: The getter snapshot is not defined for the type 'Object';
Map<dynamic, dynamic> values = dataValues.value;
values.forEach((key, values) {
messages.add(values);
});
return new ListView.builder(
shrinkWrap: true,
itemCount: messages.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Name: " + messages[index]["Text"]),
Text("Time: " + messages[index]["TextTime"]),
],
),
);
},
);
}
},
),
This solved the problem.
StreamBuilder(
stream: _dbRef.onValue,
builder: (context, snapshot) {
List<Message> messageList = [];
if (snapshot.hasData &&
snapshot.data != null &&
(snapshot.data! as DatabaseEvent).snapshot.value !=
null) {
final myMessages = Map<dynamic, dynamic>.from(
(snapshot.data! as DatabaseEvent).snapshot.value
as Map<dynamic, dynamic>); //typecasting
myMessages.forEach((key, value) {
final currentMessage = Map<String, dynamic>.from(value);
messageList.add(Message(
author: currentMessage['Author'],
authorId: currentMessage['Author_ID'],
text: currentMessage['Text'],
time: currentMessage['Time'],));
}); //created a class called message and added all messages in a List of class message
return ListView.builder(
reverse: true,
itemCount: messageList.length,
itemBuilder: (context, index) {
return ChattingDesign(
message: messageList[index],
dbpathToMsgChnl:
'TextChannels/${widget.channels['ChannelName']}/Messages',
showName: shouldShowName(
index,
messageList.length - 1,
messageList,
),
);
},
);
} else {
return Center(
child: Text(
'Say Hi...',
style: TextStyle(
color: Colors.white,
fontSize: 21,
fontWeight: FontWeight.w400),
),
);
}
},
),
According to the DataSnapshot Class Documentation there is no field called snapshot
I think there is a typo in your code.
Try this
StreamBuilder(
stream: dbRef.onValue,
builder: (context, snapshot) {
if (snapshot.hasData) {
print("Error on the way");
messages.clear();
DataSnapshot dataValues = snapshot.data! as DataSnapshot ; //here's the typo;
Map<dynamic, dynamic> values = dataValues.value;
values.forEach((key, values) {
messages.add(values);
});
return new ListView.builder(
shrinkWrap: true,
itemCount: messages.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Name: " + messages[index]["Text"]),
Text("Time: " + messages[index]["TextTime"]),
],
),
);
},
);
}
},
),

how do i replace CARD with a for loop in flutter

i want to replace the card with for loop. here's the body for my screen where i am showing the output
body: FutureBuilder<List>
(
future: db.getAllRecords("EMPLOYEE"),
initialData: List(),
builder: (context,snapshot){
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, int position){
final item =snapshot.data[position];
return Card(
child:ListTile(
title: Text(
snapshot.data[position].row[1]
),
),
);
},
)
: Center(
child:CircularProgressIndicator() ,
);
Actually, the way you wrote it is the standard way of implementation in Flutter. You could call the default ListView constructor instead of ListView.builder one and then call the for loop but that's not the best practice.
List<Widget> _buildListItems(BuildContext context, List<...> list) {
final output = List<Widget>();
for (var item in list) {
output.add(
Card(
child: ListTile(
title: Text(item.row[1]),
),
),
);
}
return output;
}
//... back to your build(context) body
body: FutureBuilder<List>(
future: db.getAllRecords("EMPLOYEE"),
builder: (context, snapshot) {
return snapshot.hasData
? ListView(
children: [
..._buildListItems(context, snapshot.data),
],
)
: Center(
child: CircularProgressIndicator(),
);
}
)

The getter 'documents' was called on null shown for a while

Im trying to retrieve name of user from firebase on appBar. It successfully retrieves it. But it displays an error on screen for few seconds before showing name of user successfully. The error os
I/flutter (24143): The following NoSuchMethodError was thrown building
StreamBuilder(dirty, state:
I/flutter (24143): _StreamBuilderBaseState<QuerySnapshot,
AsyncSnapshot>#c10cf):
I/flutter (24143): The getter 'documents' was called on null.
I/flutter (24143): Receiver: null
I/flutter (24143): Tried calling: documents
Class Data{
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
CurrentUser _currentUser = Provider.of<CurrentUser>(context, listen: false);
return Scaffold(
backgroundColor: Colors.grey[600],
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text('Property Host'),
centerTitle: true,
actions: <Widget>[
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
margin: new EdgeInsets.only(left: 50),
child: Text('Property Host',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 19),)),
StreamBuilder(stream: Firestore.instance.collection('users').where("uid", isEqualTo: userid).snapshots(),
// ignore: missing_return
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.data == null)
CircularProgressIndicator();
//final userDocument = snapshot.data;
//final title= snapshot.data.userocument['displayName']);
//CircularProgressIndicator();
return Expanded(
child: ListView.builder(
itemCount: snapshot.data.documents.length,
// ignore: missing_return
itemBuilder: (BuildContext context, int index) {
print(user.uid);
return user != null
? Container(
margin: EdgeInsets.only(top: 17, left: 40),
child: Text(
snapshot.data.documents.elementAt(index)['displayName']),
)
: IconButton(
icon: Icon(Icons.person),
// ignore: missing_return
onPressed: () {
Navigator.pushNamed(context, '/LoginScreen');
},
);
}
),
);
}
Use snapshot.hasData to ensure that you build the main widget (Expanded) after the data has been retrieved and use CircularProgessIndicator to hold its position before the data is returned
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData){
return Expanded(
child: ListView.builder(
itemCount: snapshot.data.documents.length,
// ignore: missing_return
itemBuilder: (BuildContext context, int index) {
print(user.uid);
return user != null
? Container(
margin: EdgeInsets.only(top: 17, left: 40),
child: Text(
snapshot.data.documents.elementAt(index)['displayName']),
)
: IconButton(
icon: Icon(Icons.person),
// ignore: missing_return
onPressed: () {
Navigator.pushNamed(context, '/LoginScreen');
},
);
}
),
);
}
else {
return CircularProgressIndicator();
}
}

how to convert the data coming from snapshot into List to fit in this column?

my this code is showing me error that querysnapshot is not a subtype of a list. can you edit my code and tell me how to make this error free.
buildProfilePosts() {
if (_isLoading) {
return Center(
child: Text(
"Loading...",
style: TextStyle(fontFamily: "QuickSand"),
),
);
}
return StreamBuilder(
stream: postsRef.document(widget.profileId).collection('userPosts').orderBy('timestamp', descending: true).snapshots(),
builder: (context, snapshot) {
return Column(
children: snapshot.data,
);
}
);
}
children is a property inside the widget Column, it takes a list of widgets. You should do the following:
child: Column(children: <Widget>[
StreamBuilder(
stream: postsRef.document(widget.profileId).collection('userPosts').orderBy('timestamp', descending: true).snapshots(),,
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.all(8.0),
title:
Text(snapshot.data.documents[index].data["name"]),
);
});
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
),
]),
Assuming you have a name field in your document.
Try
Column(
children: <Widget>[
...List.generate(
snapshot.data.length,
(index) {
return Container(
child: Text(snapshot.data[index].yourobject),
);
},
),
],
),

How to use a Refreshindicator on a ListView inside a Futurebuilder?

i am having trouble to reload my List which is a child of a Futurebuilder.
I am currently using data from a futureprovider which i know might be unnecessary but i wanted to learn it and leave it there for now. (Could this be a problem ?)
As you can see, i have 2 ListViews, one nested in the other. I wanted to wrap the toplevel ListView in a RefreshIndicator to load new Data from Firebase but i can't figure out how and where to update the data.
class _DayTransferListState extends State<DayTransferList> {
#override
Widget build(BuildContext context) {
final days = Provider.of<List<Day>>(context); //<-- i am populating my list with this data atm
return FutureBuilder(
future: DatabaseService().dayTransferData(), //<-- dayTransferData returns a Future<List<Day>>
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
//...
default:
if (snapshot.hasError) {
return Text('haserror');
} else {
return RefreshIndicator( //<-- refreshindicator
onRefresh: () async {
_refreshItems;
},
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: days.length,
itemBuilder: (
BuildContext context,
int dayindex,
) {
return Column(
children: <Widget>[
//...
Container(
width: double.infinity,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(kButtonRadius),
),
child: ListView.builder( //<-- second, nested ListView
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: days[dayindex].transfers.length,
itemBuilder: (BuildContext context, int index) {
return TransactionTile(
transactionIndex: index,
dayIndex: dayindex,
transfer: days[dayindex].transfers[index],
);
},
),
),
],
);
},
),
);
}
}
},
);
}
Future _refreshItems() async { //<-- method called in "onRefresh"
await DatabaseService().dayTransferData(); //<-- dayTransferData returns a Future<List<Day>>
setState(() {});
return null;
}
}
It does not work for builder. do
ListView(
children: List.generate(/*...*/),
)

Resources