flutter : not able to display image from firebase firestore - firebase

I am trying to get array of images to be displayed on container widget which is stored in firebase firestore. The url is stored with index in firestore and cloud storage. Here is the complete code below. I followed the code provided online, I am not sure what I am missing or where I went wrong. pls help me out.Thanks in advance.
class NewImage extends StatefulWidget{
List<String> urls;
int currentIndex;
VoidCallback onImageTap;
NewImage({Key key,#required this.urls,#required this.currentIndex,#required this.onImageTap})
:super(key:key);
#override
_NewImage createState() => _NewImage();
}
class _NewImage extends State<NewImage>
with SingleTickerProviderStateMixin{
List<String> images = [];
final auth = FirebaseAuth.instance;
final FirebaseFirestore fb = FirebaseFirestore.instance;
#override
void initState() {
super.initState();
getImages();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: SafeArea(
child: Column(
children: [
Container(
height: 160.0,
padding: EdgeInsets.symmetric(vertical: 15.0,horizontal: 15.0),
child: FutureBuilder(
future: getImages(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.all(8.0),
leading: Image.network(
snapshot.data.docs[index].data()["images"],
fit: BoxFit.fill),
);
});
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
),
),
],
),
),
),
);
}
Future<QuerySnapshot> getImages() async {
return FirebaseFirestore.instance.collection("users").doc(
auth.currentUser.uid).collection("images").get();
}
}

you are passing array to networkImage instead of image
change it like this
Image.network(
snapshot.data.docs[index].data()["images"][index],// [index] added
fit: BoxFit.fill),

Related

Flutter Firebase return a Querysnapshot and DocumentSnapshot in the same widget

I've spent weeks trying to sort this issue and can't seem to sort it.
I have a database with two collections userTable and userMoods
I have a future builder which is returning the name, however I am querying the userMood table to return the last created document.
I cannot seem to find a way to get this data back out.
Picture of data I am trying to retrieve:
Code is as follows:
class CorrectMood extends StatefulWidget {
const CorrectMood({Key? key}) : super(key: key);
#override
_CorrectMoodState createState() => _CorrectMoodState();
}
class _CorrectMoodState extends State<CorrectMood> {
Future<DocumentSnapshot<Map<String, dynamic>>>? _fetchedData;
#override
void initState() {
super.initState();
_fetchedData = getData();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _fetchedData,
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.hasData) {
return Scaffold(
appBar: AppBar(
title: const Text('Display the Picture'),
backgroundColor: kPrimaryColor,
),
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 8.0),
child: Column(
children: [
Center(
child:
Text(
"${snapshot.data!.data()!["firstName"]} \n\n "
"We have predicted your mood as:\n\n "
//"${DatabaseService.getMood()}\n\n"
"Please select a reason associated to your mood",
style: const TextStyle(
color: Colors.black, fontSize: 15),
textAlign: TextAlign.center,
),
),
],
),
),
],
),
),
);
}else {
return CircularProgressIndicator();
}
},
);
}
}
Future<DocumentSnapshot<Map<String, dynamic>>> getData() async {
var currentUser = FirebaseAuth.instance.currentUser;
return await FirebaseFirestore.instance
.collection('USER_TABLE')
.doc(currentUser!.uid)
.get();
}
Future<QuerySnapshot<Map<String, dynamic>>> getMood() async {
var currentUser = FirebaseAuth.instance.currentUser;
return await FirebaseFirestore.instance
.collection('userMood')
.where('userId' == currentUser!.uid)
.orderBy('createdAt', descending: true)
.limit(1)
.get();
Any help is greatly appreciated!
you can use getData() directly to your FutureBuilder.
by the way I cannot where you are calling getMood() function.

Futurebuilder snapshot has no data

CollectionReference users = FirebaseFirestore.instance.collection('Users');
FirebaseAuth auth = FirebaseAuth.instance;
String uid = FirebaseAuth.instance.currentUser!.uid.toString();
var userData;
var dbFuture;
#override
void initState() {
dbFuture = getData();
super.initState();
}
Future getData() async {
final String uid = FirebaseAuth.instance.currentUser!.uid.toString();
final DocumentSnapshot doc = await users.doc(uid).get();
users.doc(uid).get().then((DocumentSnapshot doc) {
userData = doc.data();
print(doc.data());
});
}
#override
Widget build(BuildContext context) => Scaffold(
body: FutureBuilder(
future: dbFuture,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Container(
child: Text('waiting'),
);
}
if (!snapshot.hasData) {
return Container(
child: Text('error'),
);
}
final data = snapshot.data;
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(userData['displayName']),
ElevatedButton(
onPressed: FirebaseAuth.instance.signOut,
child: Text("Log out"))
],
),
);
}),
);
I'm new in Flutter and trying to make an application for managing an academy.
I successfully saved the data at Firestore Cloud, and I can read them with
print(doc.data());
Now I want to build Profile page with those data, so I used Futurebuilder.
But snapshot always has no data.
I read documents as well, but still have no idea.
To get your data from Firebase and display them in your widgets, you have two ways, but you have to choose only one according to your needs.
With FutureBuilder()
This code will call your database and load the info you request at each build and at each setState() (responsible for updating your interface content). It could be useful for some data types, but in your case your redundant Firebase calls could cost you.
CollectionReference users = FirebaseFirestore.instance.collection('Users');
final auth = FirebaseAuth.instance;
late final uid = auth.currentUser!.uid;
#override
Widget build(BuildContext context) => Scaffold(
body: FutureBuilder(
future: users.doc(uid).get(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Container(
child: Text('waiting'),
);
}
if (!snapshot.hasData) {
return Container(
child: Text('error'),
);
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(snapshot.data!['some_data']),
Text(auth.currentUser?.displayName ?? 'user have no name'),
ElevatedButton(
onPressed: auth.signOut,
child: Text("Log out"))
],
),
);
}),
);
In the initState()
When using initState(), the code inside is called only once. To refresh the content, you will have to call getData() manually (in a setState() for example)
CollectionReference users = FirebaseFirestore.instance.collection('Users');
final auth = FirebaseAuth.instance;
late final uid = auth.currentUser!.uid;
String? someData;
#override
void initState() {
getData();
super.initState();
}
Future<void> getData() async {
users.doc(uid).get().then((doc) {
someData = doc['some_data'];
});
}
#override
Widget build(BuildContext context) => Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(someData ?? 'no data'),
Text(auth.currentUser?.displayName ?? 'user have no name'),
ElevatedButton(
onPressed: auth.signOut,
child: Text("Log out"))
],
),
),
);
Finally, if your users authenticate, you can use auth.currentUser?.displayName and auth.currentUser!.updateDisplayName('new name') to simply get and change your users' names.

Retrieve array from Firebase in Flutter

I want to retrieve array from firebase or cloud_firestore.
I have no problem with retrieving single data but i am having problem with retrieving array data
please help my beginner mind is at the verge of exploding.
I have google it and gone through many tutorials videos but i can't find the solution
database image here
pubspec.yaml
dependencies:
cloud_firestore: ^0.13.6
main.dart
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(title: Text("Flutter Fire CRUD")),
body: ListPage(),
),
);
}
}
class ListPage extends StatefulWidget {
#override
_ListPageState createState() => _ListPageState();
}
class _ListPageState extends State<ListPage> {
Future _data;
Future getUsers() async {
var firestore = Firestore.instance;
firestore.collection("users").getDocuments();
QuerySnapshot qn = await firestore.collection("users").getDocuments();
return qn.documents;
}
navigateToDetail(DocumentSnapshot users) {
Navigator.push(context,
MaterialPageRoute(builder: (context) => DetailList(users: users)));
}
#override
void initState() {
super.initState();
_data = getUsers();
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: _data,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading ...");
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index].data['name']),
onTap: () {
navigateToDetail(snapshot.data[index]);
});
},
);
}
},
),
);
}
}
class DetailList extends StatefulWidget {
final DocumentSnapshot users;
DetailList({Key key, #required this.users}) : super(key: key);
#override
_DetailListState createState() => _DetailListState();
}
class _DetailListState extends State<DetailList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("${widget.users.data['name']}"),
),
body: Column(
children: [
Container(
height: MediaQuery.of(context).size.height / 2.0,
width: MediaQuery.of(context).size.width,
child: Center(
child: Image.network(widget.users.data["img"]),
),
),
Container(
child: Card(
child: ListTile(
title: Text(widget.users.data["name"]),
subtitle: Text("Age:" + widget.users.data["age"]),
),
),
),
ListView.builder(
itemCount: widget.users.data["skills"],
itemBuilder: (context, index) {
return ListTile(
//title: Text(widget.users.data["skills"][index]),
title: here............
);
},
)
],
),
);
}
}
StreamBuilder(
stream: Firestore.instance
.collection('users')
.document(id)
.collection('chatWith')
.orderBy('timestamp', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
AppColor.colorCustom),
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Container(
alignment: Alignment.center,
child: Text(
"No Chat History Found",
style: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.normal,
fontSize:
Util.px_23 * SizeConfig.textMultiplier,
fontFamily: 'Roboto',
),
softWrap: true,
),
);
} else {
return ListView.builder(
padding: EdgeInsets.all(
Util.px_10 * SizeConfig.heightMultiplier),
itemBuilder: (context, index) => _listItem(
context, snapshot.data.documents[index]),
itemCount: snapshot.data.documents.length,
);
}
}
},
)
You can fetch list of data from firestore. this code I have used in my project. You can modify as per your requirement.

ImageIcon showing as grey

I am new to flutter and trying to load some custom images into my project and convert them into icons. The images are stored in firebase storage but I have included the url for each image in my database. When I try and load each image in and convert them to icons, they turn grey. Here is the code...
class BodyOne extends StatefulWidget {
#override
_BodyOneState createState() => _BodyOneState();
}
class _BodyOneState extends State<BodyOne> {
Future getEvents() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection('events').getDocuments();
return qn.documents;
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: getEvents(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Text('Loading...'),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
return ListTile(
leading: ImageIcon(
NetworkImage(snapshot.data[index].data['img_url']),
),
title: Align(
child: TitleText(
title: snapshot.data[index].data['eventName']),
alignment: Alignment(-1.2, 0),
),
);
},
);
}
},
),
);
}
}
And this is what it returns:
Any help would be greatly appreciated.
Do not do this, rather, just use your Image class and give height and width to the data.
leading: Image(
image: NetworkImage(snapshot.data[index].data['img_url']),
width: your_width,
height: your_height,
fit: BoxFit.cover,
color: null // this is the work around
)

Flutter/ Firestore : Class 'QuerySnapshot' has no instance getter 'document'

I have app that I want to retreive data which are messages represented in uid document from Firestore database as explained here and these messages stored like so :
ChatRoom->chatRoomId->chat-> uid-> messages
but I receive this error :
The following NoSuchMethodError was thrown building StreamBuilder(dirty, state: _StreamBuilderBaseState<dynamic,
AsyncSnapshot>#56cb5): Class 'QuerySnapshot' has no instance
getter 'document'. Receiver: Instance of 'QuerySnapshot' Tried
calling: document
The relevant error-causing widget was: StreamBuilder
file:///Users/ahmedhussain/Downloads/khamsat/Client%20Apps/HPX-KSA/hpx_ksa/lib/Screens/messages.dart:21:12
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _MessagesState.chatRoomList. (package:hpxksa/Screens/messages.dart:25:38)
Here is my code:
class _MessagesState extends State<Messages> {
Stream chatRoomsStream;
Widget chatRoomList(){
return StreamBuilder(
stream: chatRoomsStream,
builder: (context, snapshot){
return snapshot.hasData ? ListView.builder(
itemCount: snapshot.data.document.length,
itemBuilder: (context, index){
return ChatRoomTile(
username: snapshot.data.documents[index].data["chatRoomId"]
.toString().replaceAll("_", "").replaceAll(Constants.myName, "replace"),
chatRoomId:snapshot.data.documents[index].data["chatRoomId"]
);
}) : Container();
}
);
}
getUserInfogetChats() {
DatabaseService().getChatRooms(Constants.myName).then((value) {
setState(() {
chatRoomsStream = value;
});
});
}
#override
void initState() {
getUserInfogetChats();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: chatRoomList(),
);
}
}
class ChatRoomTile extends StatelessWidget {
final String username;
final String chatRoomId;
ChatRoomTile({this.username, this.chatRoomId});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>Conversation(chatRoomId: chatRoomId,)));
},
child: Container(
color: Colors.black26,
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: <Widget>[
Container(
height: 40,
width: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: kPrimaryColor,
borderRadius: BorderRadius.circular(40),
),
child: Text("${username.substring(0,1).toUpperCase()}"),
),
SizedBox(width: 8,),
Text(username),
],
),
),
);
}
}
Here is my get function to retreive chats that contains user name:
getChatRooms(String username)async{
return await Firestore.instance.collection("ChatRoom").
where("users", arrayContains: username).
snapshots();
}
The error that you received is quite clear about what the issue is. QuerySnapshot doesn't have a document property. You likely intended to use the documents property, which is more consistent with your attempt to use a ListView.
Changing instances of snapshot.data.document to snapshot.data.documents will solve this particular issue.
return StreamBuilder(
stream: chatRoomStream,
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
return ChatRoomTile(
**snapshot.data.docs[index].data()['chatRoomId']**);
},
)
: Container();
},
);

Resources