Map in GridView - firebase

I'm with a problem making a GridView where the children are a array of images from firebase, i've already tried a lot of things like changing the List type, changing ImageNetwork to NetworkImage, making map, etc, but it's always giving me the same error "The method 'map' was called on null".
return Material(
child: GestureDetector(
child: FutureBuilder(
future: Firestore.instance.collection("images-lessons").document("teste").collection("images-teste").getDocuments(),
builder: (context, snapshot){
if(!snapshot.hasData){
return Center(child: CircularProgressIndicator(),);
}
else {
return GridView(
physics: BouncingScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: imageLessonData.imageL.map((url){
return Image.network(url);
}).toList() ,);
}
}),
),
);

Related

How can i get all the user documents from a collection in flutter

I have a collection named flpProduct in firestore. I want to access all the documents stored in the flpProduct collection. I tried it with many Futurebuilder and Streambuilder but none of them worked.
I tried this
FutureBuilder<QuerySnapshot> (
future: flpProductFuture,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(
child: Text('Something went Wrong'),
);
}
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
snapshot.data.documents.forEach((element) {
print(element.data['title']);
});
return Text('done');
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Spinner(),
Text(
'Fetching Data',
style: TextStyle(color: Colors.black54, fontSize: 18.0),
)
],
);
},
),
This seems to get me the data but how can i now display this in a widget.
I already have a class that returns a container to display the information in a seperate class. I just want to pass the data to the class and display it
Better to use StreamBuilder rather than FutureBuilder
because StreamBuilder is responsible for real-time changes
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection(Your collection Name).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return new ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document.data()[key]),
subtitle: new Text(document.data()[key]),
);
}).toList(),
);
},
);

How to display any Data from Firestore using ternary operator

I was trying to fetch data from firebase and I wanted to show an Icon of Instagram only if there is any data available in the firebase collection. I used the following method to fetch the data from firebase
StreamBuilder(
stream: Firestore.instance.collection("aboutpage").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
child: Center(
child: SpinKitThreeBounce(
color: Colors.lightBlueAccent,
size: 30.0,
),
),
);
} else {
return Container(
child: ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot aboutpage = snapshot.data.documents[index];
return Column(
There is no Problem while retrieving data from firebase. Probleme is when I want to display an Instagram icon if the data is available in firebase is used ternary operator but did not work for me
"${aboutpage["name"]}" == null
? Container()
: IconButton(Icon: Icons.instagram),
onPressed: (}{}
),
I also tried using "${aboutpage["name"]}".isEmpty but dint work for me. So, How can I fetch data only if its available and if empty return empty Container?
Change the condition from "${aboutpage["name"]}" == null to aboutpage is Map && aboutpage["name"] == null.

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(/*...*/),
)

Gridview.builder with Firebase realtime database and futurebuilder

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

Resources