I have saved my phone's call list to a database and now I want to create a ListView from this database. I have already written this code. But it is not working. what is wrong with my code?
database_helper.dart
...
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database db = await instance.database;
return await db.query(table);
}
...
my_home.dart
...
FutureBuilder(
future: db.queryAllRows(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
List entries = snapshot.data.toList();
return Scrollbar(
child: ListView.builder(
itemBuilder: (context, index) {
var entry = entries[index];
var mono = TextStyle(fontFamily: 'monospace');
return Column(
children: <Widget>[
Divider(),
Text('NUMBER : ${entry.number}', style: mono),
Text('NAME : ${entry.name}', style: mono),
Text('TYPE : ${entry.callType}', style: mono),
Text(
'DATE : ${DateTime.fromMillisecondsSinceEpoch(entry.timestamp)}',
style: mono),
Text('DURATION : ${entry.duration}',
style: mono),
],
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
);
},
itemCount: entries.length,
),
);
})
...
You need to use ConnectionState inside your builder. Look at this code template: (Currently the builder return your widget without waiting for the future to complete)
return FutureBuilder<List<Map<String, dynamic>>>(
future: db.queryAllRows(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// future complete
if (snapshot.hasError || !snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
// future complete with no error and has data
List entries = snapshot.data.toList();
return Scrollbar(
child: ListView.builder(
itemBuilder: (context, index) {
var entry = entries[index];
var mono = TextStyle(fontFamily: 'monospace');
return Column(
children: <Widget>[
Divider(),
Text('NUMBER : ${entry.number}', style: mono),
Text('NAME : ${entry.name}', style: mono),
Text('TYPE : ${entry.callType}', style: mono),
Text(
'DATE : ${DateTime.fromMillisecondsSinceEpoch(entry.timestamp)}',
style: mono),
Text('DURATION : ${entry.duration}', style: mono),
],
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
);
},
itemCount: entries.length,
),
);
}
// return loading widget while connection state is active
else {
return Center(child: CircularProgressIndicator());
}
});
Related
I got a collection of questions in Firebase. The Categories are stored in an array. Now I want to to hide specific questions, if the user chose to hide it (User ID is stored in another array called hidden). This is what I tried:
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("question")
.where('category', arrayContainsAny: [widget.cid])
.where('hidden', '!=', '${user.uid}')
// also tried where('hidden', isNotEqualTo: [user.uid])
.snapshots(),
builder: (context, snapshot) {
return !snapshot.hasData
? Center(child: CircularProgressIndicator())
: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot data = snapshot.data!.docs[index];
return QuestionList(
de_du: data['de_du'],
de_sie: data['de_sie'],
de_ich: data['de_ich'],
qid: data['id'],
en: data['en'],
id: data.id,
documentSnapshot: data,
);
},
);
},
),
Any suggestions on how to get there?
Updated:
I tried to implement the transformation. I still get errors and do not get it to work. The errors I get: the first snapshot in transform is undefined. Expects an ) right after the first snapshot in transform. Also I get the info, that the user (provider of userid) is not used.
class _CategoryDetailState extends State<CategoryDetail> {
#override
Widget build(BuildContext context) {
var user = Provider.of<AuthProvider>(context);
return Scaffold(
appBar: AppBar(
title: Text(
this.widget.titel,
style: TextStyle(fontFamily: 'Gruppo'),
),
),
body: ListView(
children: [
Card(
margin: EdgeInsets.all(10),
child: Column(
children: [
Image.network(this.widget.image),
ListTile(
title: Text(this.widget.titel),
subtitle: Text(this.widget.description),
),
],
),
),
Center(
child: Text(
'Fragenübersicht:',
style: TextStyle(fontFamily: 'Caveat', fontSize: 25),
),
),
StreamBuilder<List<DocumentSnapshot>>(
stream: FirebaseFirestore.instance
.collection("question")
.where('category', arrayContainsAny: [widget.cid])
.snapshots()
.transform(snapshot => snapshot.docs.where(d => doc.data().hidden.contains(user.userid).toList())),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
return ListView.builder(
scrollDirection: Axis.vertical,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
DocumentSnapshot data = snapshot.data![index];
return QuestionList(
de_du: data['de_du'],
de_sie: data['de_sie'],
de_ich: data['de_ich'],
qid: data['id'],
en: data['en'],
id: data.id,
documentSnapshot: data,
);
},
);
}
},
),
],
),
);
}
}
There is no way to exclude a single item from a Firestore query with a condition. What you'd need is an array-does-not-contain condition, which doesn't exist.
So that means that you'll have to read the additional items from the database, and then exclude them from the stream with something like:
StreamBuilder<List<DocumentSnapshot>>(
stream: FirebaseFirestore.instance
.collection("question")
.where('category', arrayContainsAny: [widget.cid])
.where('hidden', '!=', '${user.uid}')
.snapshots()
.transform(snapshot => snapshot.docs.where(d => doc.data().hidden.contains(user.uid)).toList(),
You'll need to update the builder too to reflect that it now gets List<DocumentSnapshot> instead of QuerySnapshot.
Can someone please explain to me how to use itemCount from ListView.Builder which is inside of an FutureBuilder.
For now my FirebaseCloud Store only has one Document , and my app is returning an infinity list of documents,
I tried to use itemCount: snapshot.data.documents.length,
however, Get the error: Class 'DocumentSnapshot' has no instance getter 'documents'. Receiver: Instance of 'DocumentSnapshot' Tried calling: documents
EDIT it should only show this document one time and one of a kind if there is more than one document related to the UID
Here is my Code
final tabs = [
Center(
child: (Scaffold(
body: FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc(uid)
.get(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.data == null)
return CircularProgressIndicator();
DocumentSnapshot manuais = snapshot.data;
if (snapshot.hasData) {
print('okkk');
print(manuais.data()['nome']);
} else {
print('nopeeeee');
}
return Container(
padding: EdgeInsets.all(16),
child: ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot manuais = snapshot.data;
return Card(
color: Colors.grey[250],
child: Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
new Image.asset(
'Images/pdflogo.png',
width: 32,
),
Center(
child: Text(
(manuais.data()['nome'].toString()),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 16),
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'Compartilhar / Download'),
onPressed: () async {
var request = await HttpClient()
.getUrl(Uri.parse(manuais
.data()['documento']));
var response =
await request.close();
Uint8List bytes =
await consolidateHttpClientResponseBytes(
response);
await Share.file(
'ESYS AMLOG',
'Manual.pdf',
bytes,
'image/jpg');
}),
],
),
],
),
),
);
}),
);
})))),
````
You have to do:
itemCount : 1
Since you are only retrieving one document, when you do:
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.get()
The above will always retrieve one document since the document id will always be unique.
You need to get length like this.
itemCount: snapshot.data.data().length,
if (snapshot.hasData) {
print('okkk');
print(manuais.data()['nome']);
return Container(
padding: EdgeInsets.all(16),
child: ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot manuais = snapshot.data;
return Card(
color: Colors.grey[250],
child: Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
new Image.asset(
'Images/pdflogo.png',
width: 32,
),
Center(
child: Text(
(manuais.data()['nome'].toString()),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 16),
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'Compartilhar / Download'),
onPressed: () async {
var request = await HttpClient()
.getUrl(Uri.parse(manuais
.data()['documento']));
var response =
await request.close();
Uint8List bytes =
await consolidateHttpClientResponseBytes(
response);
await Share.file(
'ESYS AMLOG',
'Manual.pdf',
bytes,
'image/jpg') ...(all your brackets go here)
}
I am building a flutter app that fetches documents through firebase cloud firestore but i want it to show only the documents written that day. Like if i add to the collection, it will return only the documents for today. Please help
Container(
height: MediaQuery.of(context).size.height,
child: StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('all').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text('.....Loading');
}
return ListView.builder(
scrollDirection: Axis.vertical,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot all = snapshot.data.documents[index];
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text('10:00', style: TextStyle(fontSize: 18),),
SizedBox(height: 3,),
Text('05 Sep', style: TextStyle(fontSize: 13),),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Europa league', style: TextStyle(fontSize: 15),),
SizedBox(height: 2,),
Text( '${all['gg']['home']} vs ${all['gg']['away']}', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),),
you just need to put a where clause on the query like so (this gives anything made in last 24 hours):
Firestore.instance
.collection("all")
.where("created_date", isGreaterThan: DateTime.now().subtract(Duration(days: 1)) )
.snapshots();
Make sure that your data has dates, when inserting you can do it like so:
Firestore.instance
.collection("all")
.add({
'data': "data",
'created_date' : FieldValue.serverTimestamp(),
});
I want to retrive data from table in db and display it into GridView in Flutter.
At the moment I display it in a simple List but I can't display it in GridView.
Here is my code
return Scaffold(
appBar: AppBar(
title: Text("Diario di bordo"),
),
/*body: Center(
child: Text('Nessun diario presente'),
),*/
body: FutureBuilder<List>(
future: dbHelper.queryAllRows(),
initialData: List(),
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, int position) {
final item = snapshot.data[position];
//get your item data here ...
return Card(
color: RandomColor().randomColor(),
child: ListTile(
title: Text(
snapshot.data[position].row[1]),
),
);
},
)
: Center(
child: CircularProgressIndicator(),
);
},
),
...
I searched on documentation and I see this piece of code
GridView.count(
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
// Generate 100 widgets that display their index in the List.
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline,
),
);
}),
);
I don't understand how retrive data from mytable in db and show it in GridView.
You can use the GridView.Builder
return snapshot.hasData?
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
final item = snapshot.data[index];
//get your item data here ...
return Card(
color: RandomColor().randomColor(),
child: ListTile(
title: Text(
snapshot.data[index].row[1]),
),
);
},
)
: Center(
child: CircularProgressIndicator(),
);
I want to be able to create a list from an array inside a document in firestore database.
My database is like so:
I want to be able to create a streamBuilder grid from the urls inside the videosUrl array.
I tried a lot of things, but I guess that the best way is something like this one:
StreamBuilder <List<DocumentSnapshot>>(
stream: Firestore.instance
.collection('events')
.document('-LeH4rspnPTpeTLdt8hs')
.collection('participants')
.document('-LeL_TSfFDfqKgm-Io9T')
.snapshots().asyncMap((snap) async {
List<String> videosUrlArray = snap.data['videosUrl'];
var videoUrlList = <DocumentSnapshot>[];
for (var videoUrlPath in videosUrlArray) {
videoUrlList.add(await Firestore.instance.document(videoUrlPath).get());
}
print(videoUrlList);
return videoUrlList;
}),
builder: (BuildContext context, AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting: return _showLoading();
default:
return new GridView(
reverse: false,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
children: snapshot.data.map((DocumentSnapshot document) {
return Text('${snapshot.data}');
}).toList(),
);
}
},
)
but still I can't access the data!
I resolve this issue with the code below:
Widget buildGridFilesToExport(){
return new StreamBuilder(
stream: Firestore.instance
.collection('users')
.document(dataUserGlobal.userAdminId)
.collection('events')
.document(dataUserGlobal.eventId)
.snapshots(),
builder: (context, snapshot) {
print(snapshot);
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Loading...');
default:
List videosList = snapshot.data['thumbnailsUrl'];
return
videosList != null ?
new GridView.count(
crossAxisCount: 2,
childAspectRatio: 1,
children: List.generate(snapshot.data['thumbnailsUrl'].length, (index) {
return Container(
padding: EdgeInsets.all(5.0),
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 2.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
image: DecorationImage(
image: NetworkImage(snapshot.data['thumbnailsUrl'][index]),
fit: BoxFit.cover,
),
),
),
],
)
);
}),
)
:
Center(
child: Container(
width: 300,
child: Text(
'Ancora nessun video!\nVai nella cartella amici e accetta i loro video!',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'acumin-pro',
fontSize: 22,
),
),
)
);
}
},
);
}