Getting firebase data in a stream - firebase

I built an application, which gets data from the firebase (realtime db). I did it whith this code, but I want, that I always get the new data. In the internet I found something like in a stream, but I didn't find a manual for that.
Does somebody know how this works?
This is my code:
void readData() {
FirebaseDatabase.instance.reference().child('CHECK').once().then(
(DataSnapshot dataSnapShot) {
print(dataSnapShot.value);
},
);
}

I want to get the data for example every 0.5 seconds
That's not really how Firebase works. But if you want to get the data from the database once right away, and then whenever it is updated, you can use onValue for that.
That'd look something like:
FirebaseDatabase.instance.reference().child('CHECK').onValue.listen((event) {
print(event.snapshot.value);
});
Give it a try: just set up the listener with this code, run the app, and then make a change to the database in the Firebase console. You'll see the data be printed once as soon as you run the app, and then again whenever you make a change.

From what I've read in your comments, you want the function to be executed repeatedly every 0.5 seconds.
A stream is not appropriate for that. However, you can use Timer
#override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 15), (Timer t) => readData());
}
#override
void dispose() {
timer?.cancel();
super.dispose();
}
Your build() function will be called more than once once Timer.periodic is created.

Related

accessing data from a static function globally

in the init() of my splash screen page, i am calling the function of the next page in order to load the data from backend, and meanwhile the splash screen will run.
the issue here is it only calls the static function, and that function stores the data locally.
on my other page, i want data globally, so that i can access that data anywhere on that particular page.
highlights of my code is:
splash screen page init code:
void initState() {
super.initState();
FeedScreen.getdata();
}
and my next page, that is FeedScreen page, where i want data globally is:
class FeedScreen extends StatefulWidget {
#override
_FeedScreenState createState() => _FeedScreenState();
static void getdata() async{
CollectionReference collectionReference = FirebaseFirestore.instance
.collection('Feed');
var snapshot = await collectionReference.get();
snapshot.docs.forEach((result){
collectionReference.doc(result.id).collection('myfeed').snapshots().listen((event) {
var latarr,longarr,titlearr,descarr,urlarr;
for(int i=0;i<event.docs.length;i++){
urlarr.add(event.docs[i].data()['imageurl']);
latarr.add(event.docs[i].data()['lat']);
longarr.add(event.docs[i].data()['long']);
titlearr.add(event.docs[i].data()['title']);
descarr.add(event.docs[i].data()['description']);
}
});
});
}
i want to access the value of latarr,longarr,titlearr,descarr,urlarr outside the getdata() function.
Declare your variables latarr,longarr,titlearr,descarr,urlarr outside any class. For instance in your main.dart file before the void main() function. These variables will be considered as global variables and will be accessible anywhere in your app.
The best and clean approach to do this is that you use State Management. With that, you will be able to manage your variables, etc in your code smoothly and you can access those variables anywhere in your program whenever needed. Some popular ones are Provider
, Bloc and GetX.
By using state management you can easily able to Manipulate and access data anywhere in your project.

Flutter check Firebase is initialised or not and what happens if initialised multiple times?

Scenario: I have three screen of an app that I launch based on condition. One screen is buttons with other two screen options.
It works fine on a screen where I am initialising the firebase and doing fetching and all the stuff fine. void startFirebase() async { await Firebase.initializeApp(); } . However on a second screen I am doing initialisation same way but I am encountered with this error:
No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp().
Question: How to check if it is initialised (to check if initialised on first screen and wont reinitialise on second one) and - what will happen if I initialise Firebase on both the screens or if initialised twice?
update based on first provided answer:
I am not sure but calling initilise twice does not show any error. Heres how I'm trying twice:
#override
void initState() {
startFirebase();
try{
startFirebase();
}catch(e){
print(e.toString());
}
super.initState();
}
//another way:
#override
void initState() {
startFirebase();
startFirebase();
/* try{
startFirebase();
}catch(e){
print(e.toString());
}*/
super.initState();
}
No error on run tab and app works fine.
Firebase init will fail with a different message if you attempt to do it a second time.
FirebaseApp name [DEFAULT] already exists
You can check if it's already initialized as described in this other question.
Unless you have specific needs, you should instead consider instead initializing Firebase just once globally for your main app object when it first launches, and don't worry about it again after that.

Why even after putting await keyword my app will show 0?

I have called trigger function inside initState function.In trigger function i will be taking data from an API and i parsed the data using storeddata.fromjson function. Then afterwards i will store those values in variables. As far as i know initState function will be called as soon as object of this statefull widget is created. But still in app, it will show exchangeval_bitcoin as 0 for some seconds and then it will get updated(I have initialized exchangeval_bitcoin as 0). does that mean build function will be called even before completion of initState function even after putting await keyword ? And how can i implement loading screen until that value is updated ?
void triggerfun() async {
var decodedmap;
Jsonparse p = Jsonparse(url: uri);
decodedmap = await p.cryptocovert();
Storeddata s = Storeddata.fromjson(decodedmap);
setState(() {
exchangeval_bitcoin = s.getdataforbitcoin();
exchangeval_etherium = s.getdataforetherium();
exchangeval_litecoin = s.getdataforlitecoin();
});
permanent = s;
}
//calling initstate
#override
void initState() {
super.initState();
triggerfun();
}
Thanks in advance.
triggerfun() is an asynchronous function. So in your initState(), it's going to call triggerfun(), but still continue with the rest of your program. When trigger function is finished, it will set state and rebuild the widget.
The await keyword will stop the program until that line is finished, but triggerfun() as a whole is still asynchronous.

How to retrieve limited documents in firestore depending on the time they were added(For a chat app)?

Basically I want to align the messages as they are supposed to be in the usual chat app.
UPDATE: Now messages are aligned properly in the recyclerview. But whenever I send the new message it puts them on the top of the other messages. And whenever I go back and come again to that activity messages are arranged properly(even the top ones).
I just want the message which I send to show up at the bottom. Any help will be appreciated.
mLinearLayout.setReverseLayout(true);
Then:
private void loadmessage() {
mFirestore.collection("Users").orderBy("Timestamp", Query.Direction.DESCENDING).limit(10).addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot snapshots,
#Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.w("TAG", "listen:error", e);
return;
}
for (DocumentChange dc : snapshots.getDocumentChanges()) {
switch (dc.getType()) {
case ADDED:
Message message = dc.getDocument().toObject(Message.class);
messageList.add(message);
mAdapter.notifyDataSetChanged();
mMessagesList.scrollToPosition(messageList.size()-10);
break;
}
}
}
});
}
You should continue retrieving the information as you are currently doing, and then invert the order on client side, it isn't an expensive task, and trying to do what you want in Firestore is not implemented yet.
After retrieving the list, you can do something like:
Collections.reverse(messageList.clone());
Here is the same case scenario and it has the answer too. So in case anyone looking for the answer.
And This is the github repository for the features of the firestore chat app.

How to check existing data when using push ID using Firebase?

I have some problem on checking existing data on firebase. i want to check data date , timeIn and timeOut before inserting data into firebase. The code that i make doesnt work because its check data by push id.
private void addCourtBooking(){
CourtBookingDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if ((dataSnapshot.child(dateinput.getText().toString()).exists() && dataSnapshot.child(timeStartSpinner.getSelectedItem().toString()).exists()) && dataSnapshot.child(timeEndSpinner.getSelectedItem().toString()).exists()) {
Toast.makeText(getApplicationContext(), "Exist", Toast.LENGTH_LONG).show();
}else {
UCourtType = txtCourtType.getText().toString();
UPurpose = sp.getSelectedItem().toString();
UDate = dateinput.getText().toString();
UTimeStart = timeStartSpinner.getSelectedItem().toString();
UTimeEnd = timeEndSpinner.getSelectedItem().toString();
Map CourtBookinginformation = new HashMap();
CourtBookinginformation.put("courtType",UCourtType);
CourtBookinginformation.put("purpose",UPurpose);
CourtBookinginformation.put("date",UDate);
CourtBookinginformation.put("timeIn",UTimeStart);
CourtBookinginformation.put("timeOut",UTimeEnd);
CourtBookingDatabase.setValue(CourtBookinginformation);
Toast.makeText(getApplicationContext(),"Booking Successfull", Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
If I'm not wrong I understand that you wanna update that field just if the data didn't exist, and if exists, do nothing.
In that case you should use an update call to update the database, in case that your data exists and equals the same data that you wanna push, the database will do nothing:
In case that you wanna avoid the writing in any case if the data already exist,, you should use a transaction. From the documentation:
When working with data that could be corrupted by concurrent modifications, such as incremental counters, you can use a transaction operation. You give this operation two arguments: an update function and an optional completion callback. The update function takes the current state of the data as an argument and returns the new desired state you would like to write. If another client writes to the location before your new value is successfully written, your update function is called again with the new current value, and the write is retried.
Using this, you will be able to read the data, check if it exists and do whatever you need depending if it exists or not.
You can read more about read and write data in Firebase in the next link from the official documentation:
https://firebase.google.com/docs/database/android/read-and-write

Resources