I'm getting a blank screen instead of firestore data - flutter

my main code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:day_event_viewer/services/firestore.dart';
import 'package:flutter/material.dart';
class TodayEventScreen extends StatefulWidget {
#override
_TodayEventScreenState createState() => _TodayEventScreenState();
}
class _TodayEventScreenState extends State<TodayEventScreen> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: StreamBuilder(
stream: getUserDatas(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return const Text('loading data');
} else if (snapshot.hasData) {
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['name']),
// subtitle: Text(data['company']),
);
}).toList(),
);
}
return const Text('somethng\'s wrong');
}),
);
}
}
the stream getUserDatas() mentioned above:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:day_event_viewer/screens/add_screen.dart';
Stream<QuerySnapshot> getUserDatas() async* {
final uid = await getUid();
yield* FirebaseFirestore.instance
.collection('usersdatas')
.doc(uid)
.collection('profile')
.where('date', isEqualTo: DateTime.now().day)
.snapshots();
}
when I comment the code ".where('date', isEqualTo: DateTime.now().day)" 'above 4 lines' it's working fine so i think maybe my querying is the problem but i don't know how to fix it.

try this
title: Text(document.get('name')),

you should put else keyword before this line.
return const Text('somethng\'s wrong');

Related

rebuilding listview.builder every time I scroll , and 'Stream has already been listened to' error

I am using a stream builder which has another stream builder inside it. Every time I get data from the first stream I use some of this data in the other stream to finally build a list view (POSTS), but I have a problem every time I scroll down I have this error:
if (!_isInitialState) {
throw StateError("Stream has already been listened to.");
}
I tried to listen to the second stream asBroadcastStream(), and I added the case that there is no data and every time I scroll I get the notification I made that there is no data any ideas?
This is my code:
StreamBuilder<QuerySnapshot>(
stream: posts.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
return SizedBox(
height: MediaQuery.of(context).size.height * 0.69,
child: ListView(
scrollDirection: Axis.vertical,
children:
snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return StreamBuilder<DocumentSnapshot>(
stream: users
.doc(data['Uid'])
.get()
.asStream()
.asBroadcastStream(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return const Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {}
if (!(snapshot.hasData)) {
print("no data");
return SizedBox(
width: 0,
);
}
if (snapshot.connectionState ==
ConnectionState.done) {
Map<String, dynamic> daata = snapshot.data!
.data() as Map<String, dynamic>;
String username = daata['Username'];
String userimage = daata['Userimage'];
return mypost(
context,
data['title'],
data['ImageUrl'],
data['context'],
username,
userimage,
data['nlikes'],
data['ncomments'],
data['date']
.toDate()
.toString()
.split(' ')
.first);
}
return const Text("loading");
});
}).toList(),
),
);
}),
if any could help I would be happy with that.
It might interest you to know that when I run the below code (basically your code, but with my streams and mypost() function) I don't get any errors!... It scrolls fine!
import 'package:firebase_core/firebase_core.dart';
import 'package:my_app/firebase_labels.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Screen(),
);
}
}
class MyFirebase {
static FirebaseFirestore storeObject = FirebaseFirestore.instance;
}
class Screen extends StatelessWidget {
Screen({Key? key}) : super(key: key);
// Let me just define some streams here, from the same CollectionReference:
final CollectionReference posts = MyFirebase.storeObject
.collection(kCollectionConversations);
final CollectionReference users = MyFirebase.storeObject
.collection(kCollectionConversations);
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<QuerySnapshot>(
stream: posts.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
return SizedBox(
height: MediaQuery.of(context).size.height * 0.69,
child: ListView(
scrollDirection: Axis.vertical,
children:
snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return StreamBuilder<DocumentSnapshot>(
stream: users
.doc(data['Uid'])
.get()
.asStream()
.asBroadcastStream(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return const Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {}
if (!(snapshot.hasData)) {
print("no data");
return SizedBox(
width: 0,
);
}
if (snapshot.connectionState ==
ConnectionState.done) {
Map<String, dynamic>? daata = snapshot.data!
.data() as Map<String, dynamic>?;
String username = '';
String userimage = '';
if (daata != null) {
username = daata['Username'];
userimage = daata['Userimage'];
}
return mypost(
data,
// context,
data['title'],
data['ImageUrl'],
data['context'],
username,
userimage,
data['nlikes'],
data['ncomments'],
// data['date']
// .toDate()
// .toString()
// .split(' ')
// .first
);
}
return const Text("loading");
});
}
).toList(),
),
);
}),
);
}
}
Widget mypost(var data1, var data2, var data3, var data4, var data5, var data6, var data7, var data8/*, var data9,*/) {
return Container(
// height: 50,
child: Text('$data1'),
decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
);
}
If you copy-paste this code into yours, do you get errors?
What if you change the streams for yours and the mypost() for yours? Do you get errors then?

How to retrieve real time changes from Firestore document in Flutter?

I'm trying to work with realtime changes in firebase.
I found this doc but it only applies to collections. I'd like to grab data from a single document.
The sample code is below, how should I change it in order to refer to a document?
class UserInformation extends StatefulWidget {
#override
_UserInformationState createState() => _UserInformationState();
}
class _UserInformationState extends State<UserInformation> {
final Stream<QuerySnapshot> _usersStream =
FirebaseFirestore.instance.collection('users').snapshots();
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _usersStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
return ListView(
children: snapshot.data!.docs
.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['full_name']),
subtitle: Text(data['company']),
);
})
.toList()
.cast(),
);
},
);
}
}
Maybe I found a solution, it seems working
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance.collection('Users').doc(documentId).snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
return Text(" Full name ${data['Full name']} ");
}
)

FutureBuilder get data only one time

I have to get a List from Realtime Database (Firebase). I have no problem to get first time my list but if I go back and return on the future builder activity I get no data.
This is my code:
import 'package:cleverpot/Utily/Constants.dart';
import 'package:cleverpot/Utily/Function.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class AxisChart extends StatelessWidget {
AxisChart(this.title);
final String title;
final FirebaseDatabase db =
FirebaseDatabase(databaseURL: Constans.url_database);
final FirebaseAuth _auth = FirebaseAuth.instance;
List records = [];
Future getData() async {
Map data = {};
db
.reference()
.child(_auth.currentUser.uid)
.child("records")
.once()
.then((value) {
data = Map.of(value.value);
records = data[FunctionHelper.selectFolder(title)];
});
}
#override
Widget build(BuildContext context) {
return FutureBuilder<dynamic>(
future: getData(),
builder: (context, snapshot) {
return Center(
child: SfCartesianChart(
title: ChartTitle(text: "Ultima settimana"),
primaryXAxis: CategoryAxis(),
series: <LineSeries<Records, int>>[
LineSeries(
dataSource: <Records>[
Records(1, records[0]),
Records(2, records[1]),
Records(3, records[2]),
Records(4, records[3]),
Records(5, records[4]),
Records(6, records[5]),
Records(7, records[6]),
],
xValueMapper: (Records records, _) => records.day,
yValueMapper: (Records records, _) => records.records)
],
),
);
});
}
}
class Records {
Records(this.day, this.records);
final int day;
final int records;
}
If I use listen method in getData() function instead of once I resolve the problem but i don't want to stay on listen for the data. Anyone can help me? Thanks a lot!
For this example, I will use firebase firestore but I think the procedure is similar
1. Creating a stream
stream = FirebaseFirestore.instance.collection('users').snapshots();
2. Real-time read using StreamBuilder
return StreamBuilder<QuerySnapshot>(
stream: stream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading"); // this will prevent from null error
}
//when succeedeed to get data, you can make some list to show them
//
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['full_name']),
subtitle: Text(data['company']),
);
}).toList(),
);
source code from here

How to get specific fields from documentsnapshot

I have collection where i want to get fields. I have followed instructions on flutter fire and it says to use get() to retrieve documentsnapshot. I am creating a documentsnapshot object and trying to get all for a given id. Now i am trying to pass this stream into streambuilder and display specific fields. But i am getting error;
type '_BroadcastStream<DocumentSnapshot<Map<String, dynamic>>>' is not a subtype of
type
'Stream<QuerySnapshot<Object?>>?'
My code is;
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:quicktodo/model/authservice.dart';
class events extends StatefulWidget {
analytics({Key? key}) : super(key: key);
String uida = FirebaseAuth.instance.currentUser!.uid;
#override
_analyticsState createState() => _analyticsState();
}
class _ eventsState extends State<analytics> {
late final _stream;
String uid = FirebaseAuth.instance.currentUser!.uid;
void initState() {
super.initState();
setState(() {
_stream = FirebaseFirestore.instance.collection('events').doc(uid).get();
});
}
#override
Widget build(BuildContext context) {
final authService = Provider.of<AuthClass>(context);
return Scaffold(
appBar:AppBar(
leading:
IconButton(
icon: Icon(Icons.logout),
tooltip: 'List of your activities',
onPressed: () {
authService.signout(
);
},
),
title: const Text('Activity list'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add),
tooltip: 'List of your activities',
onPressed: () {
},
),
],
),
body: StreamBuilder(
stream: _stream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
// final trip = DataModel.fromSnapshot(document);
Map a = document.data() as Map<String, dynamic>;
a['id'] = document.id;
return Container(
child: Text(a['eventone']),
);
}).toList(),
);
},
),
);
}
}
Replace your stream builder with this:
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('events')
.doc(uid)
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) return Text('Something went wrong');
if (snapshot.connectionState == ConnectionState.waiting)
return Text("Loading");
Map data = snapshot.data.data();
print(data['eventide']); // should print 4
print(data['eventtwo']); // should print 5
return SizedBox();
},
);
I changed your initial stream builder because it will only work for collection snapshot, not document snapshot.

Flutter snapshot.data() always null

I'm trying to display my Data from Firestore in my Flutter Web App, but I don't get any data.
Basically I just adjusted this example: https://firebase.flutter.dev/docs/firestore/usage#realtime-changes
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class DataList extends StatefulWidget {
#override
_DataListState createState() => _DataListState();
}
class _DataListState extends State<DataList> {
#override
Widget build(BuildContext context) {
CollectionReference collectionReference = FirebaseFirestore.instance.collection('data');
return StreamBuilder<QuerySnapshot>(
stream: collectionReference.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
print('HasData: ${snapshot.hasData}');
if (snapshot.hasError) {
print(snapshot.error);
return Text('Error: ${snapshot.error}');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return new ListView(
children: snapshot.data.docs.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document.data()['name']),
subtitle: new Text(document.data()['description']),
);
}).toList(),
);
},
);
}
}
But snapshot.hasData is always null and I get this error:
[cloud_firestore/unknown] NoSuchMethodError: invalid member on null: 'includeMetadataChanges'
Getting a single Document works fine:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class GetData extends StatelessWidget {
final String documentId;
GetData(this.documentId);
#override
Widget build(BuildContext context) {
CollectionReference collectionReference = FirebaseFirestore.instance.collection('data');
return FutureBuilder<DocumentSnapshot>(
future: collectionReference.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data();
return Text("Name: ${data['name']}, Description: ${data['description']}");
}
return Text("loading");
},
);
}
}
What am I doing wrong?
I don't really need it to be Realtime, btw.
Try replacing your firestore script in index.html file with this:
<script src="https://www.gstatic.com/firebasejs/7.20.0/firebase-firestore.js"></script>