show field from realtime database flutter - firebase

I'm still learning flutter and ,I want to get a value from Realtime database in firebase and then show it in the screen.
this is the full code , i can see the value in the terminal but when i dont know how to display it on the screen
class Body extends StatefulWidget {
#override
BodyState createState() => BodyState();
}
class BodyState extends State<Body> {
final db = FirebaseFirestore.instance;
late final reference = FirebaseDatabase.instance.ref();
late DatabaseReference databaseReference ;
#override
Widget build(BuildContext context) {
DatabaseReference tempvaleur =
FirebaseDatabase.instance.ref('temperature/esofostemperature0/valeur');
tempvaleur.onValue.listen((DatabaseEvent event) async {
print(event.snapshot.value);
final data = event.snapshot.value ;
}
);
return Column(
);
}
}

You should instead use the StreamBuilder which allows you to consume the real-time stream from a Firebase collection or document.
In your case, your build method would've looked like this:
#override
Widget build(BuildContext context) {
DatabaseReference tempvaleur =
FirebaseDatabase.instance.ref('temperature/esofostemperature0/valeur');
return StreamBuilder(
stream: tempvaleur.onValue,
builder: (context, snapshot) {
if (snapshot.hasData) {
// consume your data here
var data = (snapshot.data! as DatabaseEvent).snapshot.value;
// hoping your value is a string, but just in case...
return Text(data.toString());
}
return CircularProgressIndicator();
}
);

Related

Flutter Streambuilder stream inconsistent FirebaseFirestore snapshot data

Retrieving shopping cart items my snapshot data is inconsistent. When one item is in cart I get this correctly formatted result:
{1111111111111: 1, PriceSmart: 540.0}
When two items in cart, and second item is also "PriceSmart", I get an error because returns this result:
{1111111111111: 1, PriceSmart: 300.0, 5555555555555: 1}
and should be:
{1111111111111: 1, PriceSmart: 540.0, 5555555555555: 1, PriceSmart: 300.0}
This is my firebase data structure:
First cart item:
Second cart item:
Basically is combining the "seller" (PriceSmart), when I need to return complete data from each cart item, otherwise I get an error as soon as I have more than one item in cart and seller is the same.
Please check the Stream in my code and see what is wrong with this implementation:
class PriceUpdaterWidget extends StatefulWidget {
const PriceUpdaterWidget({
Key? key,
required this.loginService,
required this.code,
required this.itemSubCategory,
}) : super(key: key);
final LoginService loginService;
final String? code;
final SubCategory? itemSubCategory;
_PriceUpdaterWidgetState createState() => _PriceUpdaterWidgetState();
}
class _PriceUpdaterWidgetState extends State<PriceUpdaterWidget> {
#override
Widget build(BuildContext context) {
CategorySelectionService catSelection =
Provider.of<CategorySelectionService>(context, listen: false);
Stream<DocumentSnapshot> priceDocStream = FirebaseFirestore.instance
.collection('shoppers')
.doc(widget.loginService.loggedInUserModel!.uid)
.collection("cartItems")
.doc(widget.code)
.snapshots();
return StreamBuilder<DocumentSnapshot>(
stream: priceDocStream,
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
SellerNameService isSellerName =
Provider.of<SellerNameService>(context, listen: false);
var sellerName = isSellerName.isSellerName;
if (snapshot.data != null) {
return Text(
snapshot.data![sellerName].toStringAsFixed(2),
textAlign: TextAlign.center,
);
} else {
return Text('No Data');
}
});
}
}
Without seeing more of your code, it's hard to make an example to exactly fit your specification, and the error you're getting doesn't match the code you posted, but, broadly, you need to:
move the Stream outside your build function and into initState
process each snapshot one at a time
stay away from processing the data in your build widget
class PriceUpdaterWidget extends StatefulWidget {
final String login, code;
const PriceUpdaterWidget(this.login, this.code);
#override
_PriceUpdaterWidgetState createState() => _PriceUpdaterWidgetState ();
}
class _PriceUpdaterWidgetState extends State<PriceUpdaterWidget> {
Stream<DocumentSnapshot> priceStream; // only one stream per widget
#override
void initState() {
super.initState();
priceStream = FirebaseFirestore.instance // set the stream once
.collection("shoppers")
.doc(widget.login)
.collection("cartItems")
.doc(widget.code)
.snapshots();
}
#override
Widget build(BuildContext context) => StreamBuilder<DocumentSnapshot>(
stream: priceStream,
builder: (context, snapshot) {
const String sellerName = "PriceSmart";
return snapshot.data == null
? const Text("No data")
: Text(
snapshot.data[sellerName].toStringAsFixed(2),
textAlign: TextAlign.center,
);
}
);
}

Firestore one-time read using Flutter, i got to printing document data in console want to output it in UI

In my Firestore DB, inside 'location' collection i have 2 docs,(named as Europe,Australia) having a field 'name' with their string values (same as their document names).
I have worked with StreamBuilder and Streams before, but this time i dont want real-time calls, but just once.
I wanna print that 'name' field data of all the docs inside location collection.
This is what my UI code looks like:
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
double spaceInBetween = 25;
#override
Widget build(BuildContext context) {
DatabaseService().getData();
return Scaffold(
body: Container(
child: Text("data here")
);
}
I wanna print all that documents data, with all their names using ListView.builder() on the HomePage.
This is my DatabaseService class (using the official FlutterFire Docs https://firebase.flutter.dev/docs/firestore/usage/ but didnt find what i was looking for)
class DatabaseService {
final locationCollection = FirebaseFirestore.instance.collection("location");
getData() async {
await locationCollection.get().then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
print(doc['name']);
});
});
}
}
Also wanted to know if there's any other way i could do this, using FutureBuilder or anything else, just wanna get field data from all docs in a collection from Firestore and print it (im still learning).
Thank you :)
I think the answer is FutureBuilder. You can create a Future method which is going to get datas from Firebase servers and return it. After that you just create a FutureBuilder which is going to help you to show datas and if something wrong with the server or the internet connection you will not get any error messages because FutureBuilder will show an CircularProgressIndicator.
I made a demo code for you to demostrate FutureBuilder.
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final locationCollection = FirebaseFirestore.instance.collection("location");
#override
void initState() {
super.initState();
}
Future<List<String>> getData() async {
List<String> name = [];
await locationCollection.get().then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
name = doc['name'];
});
});
return name;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: FutureBuilder<List<String>>(
future: getData(), // call getData method
builder: (context, snapshot) {
List<String> nameList = snapshot.data ?? []; // create a local variable which is storing data from the getData method
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListView.builder( // if getData method give datas listviewbuilder is going to show datas
itemCount: nameList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(nameList[index]),
);
},
)
: Center(child: CircularProgressIndicator()); // if something wrong with the server or with the internet you will see a CircularProgressIndicator
}),
),
),
);
}
}
In order to ensure you only get the data once, you can use a FutureBuilder and ensure you define the future outside the build method (for example in the initState) so that it doesn't get called again whenever the build method is called.
FutureBuilder
...
The future must have been obtained earlier, e.g. during
State.initState, State.didUpdateWidget, or
State.didChangeDependencies. It must not be created during the
State.build or StatelessWidget.build method call when constructing the
FutureBuilder. If the future is created at the same time as the
FutureBuilder, then every time the FutureBuilder's parent is rebuilt,
the asynchronous task will be restarted.
https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
Update the getData method of your DatabaseService class to this below:
Future<List<String>> getData() async {
final QuerySnapshot locationDataSnapshot = await locationCollection.get();
final List<String> listOfNames = locationDataSnapshot.docs
.map((QueryDocumentSnapshot documentSnapshot) =>
documentSnapshot.data()['name'] as String)
.toList();
return listOfNames;
}
This code above fetches the list of documents from the location collection and maps them to a list of names, which is then returned.
You can then get define the future object to get this data in your initState and use it in your FutureBuilder like shown below:
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<List<String>> _nameListFuture;
#override
void initState() {
super.initState();
_nameListFuture = DatabaseService().getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<String>>(
future: _nameListFuture,
builder: (context, snapshot) {
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
}
final List<String> nameList = snapshot.data;
return ListView.builder(
itemCount: nameList.length,
itemBuilder: (context, index) => Text(nameList[index]),
);
},
),
);
}
}

Getting Current user details

So for the beginning I tried to get just the name of the user from Firebase and display it on the home page but it just display the widget's name.
Im using google/facebook/anonymous/email & password login methods.
Firebase instance
Future getCurrentUser() async {
print('done');
return _auth.currentUser;
}
The widget that suppose to get the user details
class GetCurrentUser extends StatefulWidget {
#override
_GetCurrentUserState createState() => _GetCurrentUserState();
}
class _GetCurrentUserState extends State<GetCurrentUser> {
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: Provider.of(context).auth.getCurrentUser(),
builder: (context, snapshot) {
print('done');
if (snapshot.connectionState == ConnectionState.done ) {
return snapshot.data.displayName;
} else {
return Text('error');
}
},
);
}
}
And the String that stores the user's name
String userProfile = GetCurrentUser().toString();
Found a solution!
using the code of this thread's answer How to get the current user id from Firebase in Flutter
I took the void function he made and used it inside the widget I wanted to change the user name too and setState for that string
final FirebaseAuth _ath = FirebaseAuth.instance;
void inputData() {
final User user = _ath.currentUser;
setState(() {
userProfile = user.displayName;
});
}

FetchData From Cloud FireStore Firebase in flutter (dart)

This is my Fire Base cloud store structure the data is stored in the document is as Map<string,Dynamic>
What Would be the Query if i want to fetch the username to corresponding uid ?
Also , i want return the username to a text widget
Language Used : Dart
String getUserName (User user) {
String username;
/* Query */
return username;
}
class username extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("USER NAME : " + getUserName());
}
}
Please Help!
You can use the FlutterFire Package to read Data from your Firestore
https://firebase.flutter.dev/docs/firestore/usage/#one-time-read
Take a look at their example, you only have to make a few Adjustments:
class GetUserName extends StatelessWidget {
final String documentId; // This is your User UID
GetUserName(this.documentId);
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.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("USER NAME: ${data['name']}");
}
return Text("loading");
},
);
}
}

Can not retrieve documents from Firebase

So I'm trying to retrieve all documents from a certain collection 'avtvity' in my Firestore through loadmap() method. I have put the function in my initState() since I want to immediately add the data to my Place which is a class i created to add places. However, the data is not being placed in my 'places' which is a List which makes me question that the loadMap() is not being called.
any idea how to fix it?
here is the code:
class PlaceTrackerApp extends StatefulWidget {
final FirebaseUser firebaseUser;
PlaceTrackerApp({this.firebaseUser});
#override
_PlaceTrackerAppState createState() => _PlaceTrackerAppState();
}
class _PlaceTrackerAppState extends State<PlaceTrackerApp> {
AppState appState = AppState();
#override
void initState() {
super.initState();
print(widget.firebaseUser);
loadMap();
}
static StreamBuilder<QuerySnapshot> loadMap() {
return StreamBuilder(
stream: Firestore.instance.collection('avtivity').snapshots(),
builder: (context, snapshot) {
if(!snapshot.hasData) return Text("Loading... Please wait,");
for (int i = 0; i < snapshot.data.documents.length; i++) {
StubData.places.add(new Place(
id: snapshot.data.documents[i]['id'],
latLng: snapshot.data.documents[i]['latlng'],
name: snapshot.data.documents[i]['title'],
description: snapshot.data.documents[i]['description'],
starRating: snapshot.data.documents[i]['rating'],
category: PlaceCategory.activities,
));
}}
);
}
Here is a screenshot of database:

Resources