问题
i want to read data from firestore in a listtile i dont want to use streambuilder i want to access the documents field individually i try this but not working
class ProductList extends StatelessWidget {
Stream<DocumentSnapshot> snapshot = Firestore.instance.collection("listofprods").document('ac1').snapshots();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black)
),
child: ListTile(
title: Text(snapshot['name']),//here error
),
)
],
回答1:
Try this:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class WeightChart extends StatefulWidget {
@override
_WeightChartState createState() => _WeightChartState();
}
class _WeightChartState extends State<WeightChart> {
dynamic data;
Future<dynamic> getData() async {
final DocumentReference document = Firestore.instance.collection("listofprods").document('ac1');
await document.get().then<dynamic>(( DocumentSnapshot snapshot) async{
setState(() {
data =snapshot.data;
});
});
}
@override
void initState() {
super.initState();
getData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Weight'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black)
),
child: ListTile(
title: Text(data['name']),//here error
),
)
]
)
),
);
}
}
回答2:
you can use StreamBuilder
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('books').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Loading...');
default:
return new ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['title']),
subtitle: new Text(document['author']),
);
}).toList(),
);
回答3:
Use Streambuilder for stream in flutter
StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance.collection("listofprods").document('ac1').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return LinearProgressIndicator();
return _buildList(context, snapshot.data.documents);
},
);
回答4:
without stream and in a stateless widget, I made it with:
- Function running at first in build
- This function need to be "async-await" in order to get data
- Use of toString, get and data for access the desire element.
code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
DocumentSnapshot snapshot; //Define snapshot
class ProductList extends StatelessWidget {
void getData()async{ //use a Async-await function to get the data
final data = await Firestore.instance.collection("listofprods").document('ac1').get(); //get the data
snapshot = data;
}
@override
Widget build(BuildContext context) {
getData(); //run the function in build
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black)
),
child: ListTile(
title: Text(snapshot.data['name'].toString()),//ok no errors.
),
)
],
),
),
),
);
}
}
the last code maybe gets some errors on diferents versions of cloud_firestore the version i use is
- cloud_firestore: ^0.13.7
- firebase_core: ^0.4.5
and other error is a red screen with some null on text, this is fix with a FutureBuilder instead to call directly de data, in this way:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class ProductList extends StatelessWidget {
@override
Widget build(BuildContext context) {
Future<String> data2() async {
var data1 = (await Firestore.instance
.collection('listofprods')
.document('ac1')
.get())
.data['name']
.toString();
return data1;
}
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
decoration:
BoxDecoration(border: Border.all(color: Colors.black)),
child: ListTile(
title: FutureBuilder(
future: data2(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
print(snapshot.data);
return Text(snapshot.data);
},
), //ok no errors.
),
),
],
),
),
),
);
}
}
回答5:
This works in FlutterFire! I used DocumentSnapshot and await.
By using DocumentSnapshot, you can get the document including document fields and its values.
A DocumentSnapshot contains data read from a document in your Cloud Firestore database. The data can be extracted with data() or get() to get a specific field.
The keyword await will wait until any async functions are finished.
You can use the await keyword to get the completed result of an asynchronous expression. The await keyword only works within an async function.
import 'package:cloud_firestore/cloud_firestore.dart';
final db = FirebaseFirestore.instance;
// Get document with ID totalVisitors in collection dashboard
await db.collection('dashboard').doc('totalVisitors').get()
.then((DocumentSnapshot documentSnapshot) {
// Get value of field date from document dashboard/totalVisitors
firestoreDate = documentSnapshot.data()['date'];
// Get value of field weekOfYear from document dashboard/totalVisitors
firestoreWeek = documentSnapshot.data()['weekOfYear'];
}
);
来源:https://stackoverflow.com/questions/59529177/how-to-read-data-from-firestore-flutter