Null check operator used on a null value - flutter

body: StreamBuilder(
stream: db.collection('products').where('category', isEqualTo: 'category').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if(snapshot.hasError){
Fluttertoast.showToast(msg: 'Something error');
}
if(snapshot.connectionState == ConnectionState.waiting) {
CircularProgressIndicator();
}
final values = snapshot.data!.docs;
return ListView.builder(
itemCount: values!.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(values![index]['name']),
),
),
);
}
);
},
),
The following _CastError was thrown building StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(dirty, state: _StreamBuilderBaseState<QuerySnapshot<Map<String, dynamic>>, AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>>>#c87c1):

you missed return in your if blocks, so those widgets are not being returned, this redirect to the snapshot.data!.docs widget which is null initially, change it to this:
body: StreamBuilder(
stream: db.collection('products').where('category', isEqualTo: 'category').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if(snapshot.hasError){
Fluttertoast.showToast(msg: 'Something error');
return Text("error"); // add this to showcase the error
}
if(snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator(); // add this to show loading when data is fetching
}
final values = snapshot.data!.docs;
return ListView.builder(
itemCount: values!.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(values![index]['name']),
),
),
);
}
);
},
),

Related

Fetch data from Firestore Document using StreamBuilder

In my Flutter app, I'm trying to get the data from a Document in Firestore. Here's the data I want to get :
Firestore document's data
I need to fetch that url from the Document. So far, when I needed to fetch data from a collection, I used a Streambuilder. But here I need to fetch data from a document, so I get this error message :
late Stream<DocumentSnapshot<Map<String, dynamic>>>? personnalData =
FirebaseFirestore.instance
.collection('Decembre')
.doc(uid)
.collection('Docs')
.doc('test')
.snapshots();
StreamBuilder<QuerySnapshot>(
stream: personnalData, // Error: The argument type 'Stream<DocumentSnapshot<Map<String, dynamic>>>?' can't be assigned to the parameter type 'Stream<QuerySnapshot<Map<String, dynamic>>>?'.
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
return Stack(
children: snapshot.data!.docs
.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return PageView.builder(
controller: _controller,
itemCount: 3,
itemBuilder: (context, index) {
return Container(
child: InteractiveViewer(
minScale: 0.1,
maxScale: 4.0,
child: Image.network(
// FETCH URL FROM DOCUMENT 'TEST'
width:
MediaQuery.of(context)
.size
.width,
fit: BoxFit.cover,
loadingBuilder: (context,
child,
loadingProgress) {
if (loadingProgress ==
null) {
return child;
} else {
return Center(
child:
CircularProgressIndicator(),
);
),
);
}),
),
],
),
),
);
},
child: Text('Open'));
})
.toList()
.cast(),
);
},
),
Any suggestions ?
I found the solution !
The problem was that I was trying to fetch data from a DocumentSnapshot using a StreamBuilder<QuerySnapshot> instead of StreamBuilder<DocumentSnapshot>
Here's how I solved it :
late Stream<DocumentSnapshot<Map<String, dynamic>>> personnalData =
FirebaseFirestore.instance
.collection('Decembre')
.doc(uid)
.collection('Docs')
.doc('test')
.snapshots();
StreamBuilder<DocumentSnapshot>(
stream: personnalData,
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!['url']);
}
return CircularProgressIndicator();
}),
This code is working well for me. I hope that will help somebody !
Maybe what you need is just to specify the type of the QuerySnapshot:
late Stream<DocumentSnapshot<Map<String, dynamic>>> personnalData = // like this FirebaseFirestore.instance
.collection('Decembre')
.doc(uid)
.collection('Docs')
.doc('test')
.snapshots();
because the snapshots() is a method that returns Stream<DocumentSnapshot<Map<String, dynamic>>>, and setting only Stream<DocumentSnapshot> will be considered as a different type, which throws the error.
maybe you can try
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: personnalData,
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
return Stack(
children: snapshot.data!.docs
.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return PageView.builder(
controller: _controller,
itemCount: 3,
itemBuilder: (context, index) {
return Container(
child: InteractiveViewer(
minScale: 0.1,
maxScale: 4.0,
child: Image.network(
// FETCH URL FROM DOCUMENT 'TEST'
width:
MediaQuery.of(context)
.size
.width,
fit: BoxFit.cover,
loadingBuilder: (context,
child,
loadingProgress) {
if (loadingProgress ==
null) {
return child;
} else {
return Center(
child:
CircularProgressIndicator(),
);
),
);
}),
),
],
),
),
);
},
child: Text('Open'));
})
.toList()
.cast(),
);
},
),
in streamBuilder you can add <DocumentSnapshot<Map<String, dynamic>>> same as you create stream.
Refer the following example:
StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance.collection('Decembre').doc(uid).collection('Docs').doc('test').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot doc = snapshot.data!.docs[index];
return Column(
children:[
Text(doc['url'])
);
});
} else {
return Text("No data");
}
},
)

why am not getting data from firestore?

hello I have the list of categories in my firestore i want to fetch them in to a listview it only shows CircularProgressIndicator then after it disapear nothing comes on screen where did get wrong?
Expanded(
child: _appwidget.customeTextFormField(
hint: "Select category",
icon: InkWell(
onTap: () {
showFancyCustomDialog(context,
height: 500,
width: 500,
title: "Add / Select / Delete Category",
widget: FutureBuilder<DocumentSnapshot>(
future: _services.category
.doc("ProductCategories")
.get(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot>
snapshot) {
if (snapshot.hasError) {
return Text('error');
}
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Container(
child:
Center(child: CircularProgressIndicator()),
);
}
return ListView.builder(
itemBuilder:
(BuildContext context,
int index) {
return ListTile(
title: Text(snapshot.data!["Categories"]
[index]["name"]),
);
},
itemCount: snapshot.data!['Categories'] ==
null
? 0
: snapshot.data!['Categories'].length,
);
}),
addButton: Container());
},
child: Icon(Icons.list)))),
You forgot to tackle the condition in which you have data.
Just add if(snapshot.hasData) & return your ListView.builder(), because in other conditions you are not sure whether you have received the data or not.
return Expanded(
child: _appwidget.customeTextFormField(
hint: "Select category",
icon: InkWell(
onTap: () {
showFancyCustomDialog(context,
height: 500,
width: 500,
title: "Add / Select / Delete Category",
widget: FutureBuilder<DocumentSnapshot>(
future: _services.category
.doc("ProductCategories")
.get(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot>
snapshot) {
if (snapshot.hasError) {
return Text('error');
}
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Container(
child:
Center(child: CircularProgressIndicator()),
);
}
if(snapshot.hasData){
return ListView.builder(
itemBuilder:
(BuildContext context,
int index) {
return ListTile(
title: Text(snapshot.data!["Categories"]
[index]["name"]),
);
},
itemCount: snapshot.data!['Categories'] ==
null
? 0
: snapshot.data!['Categories'].length,
);
}
}),
addButton: Container());
},
child: Icon(Icons.list))));

Error: the operation '[]' is not defined for the type 'object'

I am using Null -Safety then I keep getting this error, anywhere I user snapshot in my code
here is the error
here is my code
StreamBuilder(
stream: firestore
.collection('interest')
.doc('${auth.currentUser?.uid}')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!['Interest'].length ,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(top: 12.0),
child: bottomCardList(
'assets/1 (6).jpeg',
snapshot.data!['Interest'][index]
.toString(),
),
);
});
}),
Thanks
i solve this by using the type
StreamBuilder<DocumentSnapshot<Map>>(
stream: firestore
.collection('interest')
.doc('${auth.currentUser?.uid}')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!['Interest'].length ,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(top: 12.0),
child: bottomCardList(
'assets/1 (6).jpeg',
snapshot.data!['Interest'][index]
.toString(),
),
);
});
}),
There are a few solutions:
Provide a type to your StreamBuilder:
StreamBuilder<DocumentSnapshot<Map>> (...)
Provide a type to the second parameter of your builder:
builder: (context, AsyncSnapshot<Map> snapshot)
Use as to downcast the Object to Map
(snapshot.data as Map)['key']

Flutter query (where + order by) from firebase firestore returns error

My queries from flutter app return error. any ideas why?
Query user = FirebaseFirestore.instance.collection('users').where('approvedStatus', isEqualTo: true).orderBy('name');
How i show data from query
Container(
child: StreamBuilder(
stream: user.snapshots(),
builder: (BuildContext context, snapshot) {
if (snapshot.hasError) {
return Text('Snapshot return error');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading ..."); // CircularProgressIndicator();
}
return Container(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (context, i) {
return Card(
child: ListTile(
title: Text(snapshot.data.docs[i]['name'].toString()),
),
);
},
),
);
},
),
),
The result i got is snapshot return error
Nevermind guys. I found the problem after printing snapshot.error
[cloud_firestore/failed-precondition] The query requires an index.
I just follow the link provided and it solve the problem . Thanks

Flutter: When the snapshot is empty the widget disappears

I am trying to build a search list, the list is working fine but if the result is empty i need to show no data. I tried the following code but the widget holds for a second and then disappear
FutureBuilder(
future: getSearchedProducts(widget.searchString),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(
child: Container(
child: Text('No Data Found.'),
),
);
} else {
return ListView.builder(
shrinkWrap: true,
itemCount: searchResult.length,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Image.network(searchResult[index].proThumbnail),
title: Text(searchResult[index].proName),
onTap: () {
print(searchResult[index].proName);
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ProductPage(prodid: searchResult[index].proId);
}));
},
),
);
});
}
})
Can anyone help me with this.
Thank you in advance.
I just write the code as below and it works.
FutureBuilder(
future: getSearchedProducts(widget.searchString),
builder: (BuildContext context, AsyncSnapshot snapshot) {
print('length of list ${searchResult.length}');
if (searchResult.length==0) {
return Center(
child: Text('No data'),
);
}
else if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
else {
return ListView.builder(
shrinkWrap: true,
itemCount: searchResult.length,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Image.network(searchResult[index].proThumbnail),
title: Text(searchResult[index].proName),
onTap: () {
print(searchResult[index].proName);
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ProductPage(prodid: searchResult[index].proId);
}));
},
),
);
});
}
}),
In your Code in Else part before - return ListView.builder- add the following code.
...
else {
if (searchResult.length == 0)
{
return Center(child: const Text('No Date'));
}
return ListView.builder .....