I want to start a Fragment with information I have to get from the Firebase database when I click the button. For the sake of an example, say I want to open a user profile and I need to load all data from database > users > uid AND I need information from database > messages (e.g. the posts of the user).
Now my approach would be this:
(The following code is a part of the #Override public void onClick(View v) { } method of the button that shall start the Fragment)
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
User user = snapshot.getValue(User.class);
// start the fragment here ...
}
});
But since I need information from database > messages as well, I'm not sure how to do this in a good way. The following would be possible:
(The following code is a part of the #Override public void onClick(View v) { } method of the button that shall start the Fragment)
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
User user = snapshot.getValue(User.class);
// just add another listener on the other reference
dbRef_2.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
MessagesInfo message = snapshot.getValue(MessagesInfo.class);
// start the fragment here ...
}
});
}
});
But this seems not to be the best way to do it since we just got two SingleValueEvent listeners nested. And if we'd need more information, like 10 different database "locations", we'd need to nest 10 of these listeners.
So what is a good way?
Unfortunately, there is no method to fetch multiple locations at once, you could do this with a custom script if you are expecting to re-use it multiple times but it would always result in a loop that fetches each item.
It's also important to note that the order in which the queries were sent is also the order in which the server processes them.
Related
is it possible for android to automatically update the data that is stored in real time database? For example, the data that is gonna be stored in my firebase real time database is going to be constantly changing within seconds because it is connected to a back-end system that triggers its change. Could it be done that every time the data has changed, the textView in my application that shows that data gets updated every time as well ? For now, I have a button that updates the data on click, but is it possible to update it automatically without a button? My code looks like this for now :
a = findViewById(R.id.insidetempView);
b = findViewById(R.id.filterView);
c = findViewById(R.id.humiditytextView);
d = findViewById(R.id.CO2textView);
Button saveButton = findViewById(R.id.numbersButton);
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
reff = FirebaseDatabase.getInstance().getReference().child("Numbers");
reff.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String CO2 = snapshot.child("CO2").getValue().toString();
String filter = snapshot.child("Filter").getValue().toString();
String humidity = snapshot.child("Inside_humidity").getValue().toString();
String temp = snapshot.child("Inside_temperature").getValue().toString();
a.setText(temp);
b.setText(filter);
c.setText(humidity);
d.setText(CO2);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
This blog post should provide you with the solution you need go through it and you will be able to do what you want https://firebase.googleblog.com/2017/12/using-android-architecture-components.html
it has information on using android Architecture Components with Firebase Realtime Database. and when you observe LiveData you can implement all changes instantly
I'm using firebase with android to create a simple chat app. When the user chooses another user to chat with I want to check whether they've chatted together or not.
In onCreate() method I'm retrieving all the rooms that the current user used before, and I'm putting them in an arraylist called MyChatRooms<>.
Then I want to check each room to see the users of the room.
The problem is that the loop I'm using to iterate through rooms name is finishing before I'm able to retrieve any data from the database.
I know there's similar questions to mine, but none of the answers worked for me.
Here's the related code:
if (!MYChatRooms.isEmpty()) {
for (j = 0; j < MYChatRooms.size(); j++) {
roomref.child(MYChatRooms.get(j)).child("First User").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot1) {
if (!dataSnapshot1.getValue().toString().equals(Username) && dataSnapshot1.getValue().toString().equals(NUsername)) {
Users += dataSnapshot1.getValue().toString() + ",,, ";
} else if (dataSnapshot1.getValue().toString().equals(Username)) {
roomref.child(MYChatRooms.get(j)).child("Second User").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot2) {
if (dataSnapshot2.getValue().toString().equals(NUsername)) {
Users += dataSnapshot2.getValue().toString() + ",,, ";
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
I would suggest that you change the structure of your data. Imagine if a user has 100 chats that means your have to query 200 times to Firebase that of course does not look feasible.
What i would suggest is that your add a recentChat list in every user and whenever a user starts a new chat with someone you add the id of the second user to that list. That way you can track easily with whom the current user has interacted with.
It structure in firebase can look something like this:
User
recentChats
id of the other user
Try to change you database hierarchy or use firestore instead of real time database
Please check the following topic: https://firebase.google.com/docs/database/usage/optimize?
In my case, I had added and index column and limited the query in Firebase Rules.
I am trying to change child key in Firebase like 'Users' is a child and having different children like 'user1' , 'user2' , 'user3'.
But problem is that my code works for single application when new user installed application data is override on previous child.
Instead of using .setValue(hashMap) use .setValue(hashMap).push()
You can check if the user exists already then do not push the new one.
databaseReference.child("User"+Integer.toString(i)).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.exists()){
databaseReference.child("User"+Integer.toString(i)).setValue(hashMap);
}else{
// Don't create user. Start other activity or whatever you need to do
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Let me know if this worked for you
Right now I'm developing an android app, and I just started to work with Firebase.
My question is: How can I retrieve data from the firebase database, without use listeners ?
In my game, I'm saving the high scores of all the users, and I need to take the data from the database when user go into "leader-boards" page.
I saw some solutions, which is not good for my case.
One of them is:
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
This solution is not good for me, because I cant afford to my app to go into the server every time high score of user is changing, because if I would have 20,000 people who playing at the same time, then the game will stuck.
so I cant use this listener, because it will make the game very slow.
My goal is to to find a way to change the high score, without alerting the other people who is currently playing the game, I mean that I need to update every user score for his own, and when user go to the "leader boards" page, only then I will go to the server.
what is the right solution here ?
Or can I use this listener in another way?
If my question is not clear, then ask me in the comment please.
Thank you !!
my lines:
public static void setUserHighScoreToServer(Context context,boolean isClassic,int scoreNum)
{
com.firebase.client.Firebase mRef;
mRef= new com.firebase.client.Firebase("...");
String name = InternalStorage.getUserName(context);
String classic = "";
if(isClassic)classic="Classic";
else classic="Arcade";
com.firebase.client.Firebase mRefChild = mRef.child(name+classic);
mRefChild.setValue(String.valueOf(scoreNum));
}
This is the OFFICIAL way to retrieve data once without listening for data changes.
// Add all scores in ref as rows
scores.addListenerForSingleValueEvent( new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot child : snapshot.getChildren()) {
...
}
}
}
more information here: https://firebase.google.com/docs/reference/android/com/google/firebase/database/DataSnapshot
If you donĀ“t need to update on real time, you can always do a Rest api call to your database.
Just do a GET call to retrieve your data
https://[PROJECT_ID].firebaseio/[path].json
and you are good to go
You can also update or create new keys using rest api calls.
This is how my firebase database looks like.
I want to access the node accepting-status and say patient23 for example. I can easily do this by using addListenerForSingleValueEvent on nodes accepting-status and patient23 separately but then it would take me two different requests to get the required data. I can also get the required data by single request by adding addListenerForSingleValueEvent on the parent node beacon-final but then that would retrieve huge data because the patients are in large numbers.How do I do it in a single request and yet only retrieve only the required nodes. Thanks.
...but then it would take me two different requests to get the
required data.
The Firebase database is all one JSON object. If you select one part, you'll get everything underneath.
But, Firebase uses WebSockets, which is a persistent connection to the server. This means that you don't have to worry about making a request, because the only HTTP request that gets made is in the very beginning to establish the socket.
So in your case it's completely feasible to make two separate "requests" for the data, because there's no real overhead to consider. The device's radio is already on, and a WebSocket header is merely 6 bytes.
You can easily create a listener on /accepting-status, as well as /patients/patient23. This is a standard Firebase practice to have multiple listeners.
// Get a root reference
Firebase rootRef = new Firebase("<my-firebase-app>");
// accepting-status ref
Firebase statusRef = rootRef.child("accepting-status");
// patient23 ref
Firebase patientRef = rootRef.child("patients").child("patient23");
// Listen for status updates
statusRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
System.out.println(snapshot.getValue());
}
#Override
public void onCancelled(FirebaseError firebaseError) {
// error
}
});
// Listen for patient updates
patientRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
System.out.println(snapshot.getValue());
}
#Override
public void onCancelled(FirebaseError firebaseError) {
// error
}
});