public class DataService {
private static DataService ourInstance = new DataService();
private DatabaseReference mDatabase;
public static DataService getInstance() {
return ourInstance;
}
public ArrayList<UserDatabase> getFriendList() {
mDatabase = FirebaseDatabase.getInstance().getReference().child("users");
final ArrayList<UserDatabase> list = new ArrayList<>();
mDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
UserDatabase userDatabase = dataSnapshot.getValue(UserDatabase.class);
list.add(userDatabase);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
return list;
}
}
I am trying to fetch my users database from the users node. It's acting really weird. When I set a breakpoint at the onChildAdded function, it will retrieve all the users and add it to the list.
However, if I don't set a breakpoint there, it is not getting anything and the list size is 0. Does anyone have any idea what is going on? Thanks in advance!
Data is loaded and synchronized from Firebase asynchronously.
It's easiest to see what's causing your problem if you add a few well-placed logging statements:
public ArrayList<UserDatabase> getFriendList() {
mDatabase = FirebaseDatabase.getInstance().getReference().child("users");
final ArrayList<UserDatabase> list = new ArrayList<>();
System.out.println("Attaching listener");
mDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
System.out.println("Got data");
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
public void onChildRemoved(DataSnapshot dataSnapshot) {}
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
public void onCancelled(DatabaseError databaseError) {}
});
System.out.println("Returning list");
return list;
}
The output will print in this order:
Attaching listener
Returning list
Got data
That is probably not the order you expected. But it does explain why the list of empty if you run the code as is.
The reason for this is that Firebase loads and synchronizes the data asynchronously. Like most modern web APIs it doesn't wait for the result to return (that would lead to a horrible user-experience), but instead lets the program continue and calls back into your code when it gets (new) data.
The way to deal with this behavior is to reframe the flow of your program from "first get the list of friends, then do xyz with it" to "whenever the list of friends changes, do xyz with it".
For example say that you simply want to print how many friends there are. Your current approach is probably:
ArrayList<UserDatabase> friends = getFriendList();
System.out.println("There are "+friends.size()+" friends");
With Firebase one way to handle this is to move the operation into getFriendList():
public void getFriendList() {
mDatabase = FirebaseDatabase.getInstance().getReference().child("users");
final ArrayList<UserDatabase> list = new ArrayList<>();
mDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
UserDatabase userDatabase = dataSnapshot.getValue(UserDatabase.class);
list.add(userDatabase);
System.out.println("There are "+friends.size()+" friends");
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
public void onChildRemoved(DataSnapshot dataSnapshot) {}
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
public void onCancelled(DatabaseError databaseError) {}
});
}
Related
I am using firebase real-time database to store and retrieve data but for some reason, I am unable to achieve what I want.
I want to get 20 records at a time on swipe refresh layout.
My data looks like:
Initially, I load 50 records:
chat.limitToLast(default_num_of_messages).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map map = dataSnapshot.getValue(Map.class);
String user_id = map.get("user_id").toString();
String message = map.get("message").toString();
String timestamp = map.get("timestamp").toString();
Log.d("MAP", map.toString());
ChatMessage chat_message = new ChatMessage();
chat_message.setUser_id(user_id);
chat_message.setMessage(message);
chat_message.setTimestamp(Long.parseLong(timestamp));
Log.d("CHAT MSG", chat_message.toString());
if(Integer.parseInt(user_id) == Utils.getInstance().getLoggedInUser().getId()) {
addMessageBox(chat_message, 1);
}
else{
addMessageBox(chat_message, 2);
}
}
after these on refresh, I want to load 20 more. I am trying to do something like these. but it does not seem to return.
#Override
public void onRefresh() {
if(refresh_toggle) {
swipe_view.setRefreshing(true);
Log.d("CHAT", "REFRESHED!!!");
//reload new data
chat.orderByChild("timestamp").endAt(10).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map map = dataSnapshot.getValue(Map.class);
String user_id = map.get("user_id").toString();
String message = map.get("message").toString();
String timestamp = map.get("timestamp").toString();
Log.d("CHATS", map.toString());
ChatMessage chat_message = new ChatMessage();
chat_message.setUser_id(user_id);
chat_message.setMessage(message);
chat_message.setTimestamp(Long.parseLong(timestamp));
swipe_view.setRefreshing(false);
if(Integer.parseInt(user_id) == Utils.getInstance().getLoggedInUser().getId()) {
addMessageBox(chat_message, 1);
}
else{
addMessageBox(chat_message, 2);
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
#Override
public void onCancelled(FirebaseError firebaseError) {}
});
}
}
As you can see I am trying to orderByChild "timestamp" and then tried different combination of startAt(), endAt() but nothing seem to work.
Try this:
int number_item_load = 10; //changed number if you want
public void loadMore(int offset, String theLastValue) {
// theLastValue: depend on your orderByChild() 's value
mDatabase = FirebaseDatabase.getInstance().getReference().child(Utils.FB_ROOT);
mEventListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (isAlreadyAttach()) {
// Get your item and callback to view and insert to listView
}
} ...
};
mDatabase.orderByChild("yourvalue").startAt(theLastValue).limitToFirst(number_item_load ).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// TODO Finished loaded number_item_load item
OnLoadedFinish(); //
mDatabase.removeEventListener(mEventListener); // Remove listener after load
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
mDatabase.orderByChild("yourvalue").startAt(theLastValue).limitToFirst(number_item_load ).addChildEventListener(mEventListener);
}
It worked perfectly in my case. Goodluck
I am using Google Firebase to store database of user heartbeat from Android Wear.
Now I'm trying to retrieve the heartbeat value on child "tmpHR" but the value keeps on showing null.
Here is the structure of my database :
I want to retrieve int tmpHR child value under the random key
Here's my lines of code :
Integer hrValue;
ArrayList<Integer> array1;
array1 = new ArrayList<>();
DatabaseReference userdatabase = FirebaseDatabase.getInstance().getReference().child("Users");
DatabaseReference ref = userdatabase.child(user.getUid()).child("hrvalue").child("nilaihr");`
`ref.addChildEventListener(new ChildEventListener() {`
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot uniqueKeySnapshot : dataSnapshot.getChildren()) {
//Loop 1 to go through all the child nodes of nilaihr
//store random key in uniqueKeySnapshot
Integer hrValue = uniqueKeySnapshot.child("tmpHR").getValue(Integer.class);
// random key -> child tmpHR -> store in Integer hrValue
Log.i("heart rate value", "hrvalue " + hrValue);
showData(dataSnapshot);
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void showData(DataSnapshot dataSnapshot) {array1.add(hrValue);}
And here's the logcat :
05-15 19:01:55.824 27624-27624/com.example.amiramaulina.retrievedataheartbeat I/database array: array database [null, null, null,....., null]
05-15 19:01:55.824 27624-27624/com.example.amiramaulina.retrievedataheartbeat I/heart rate value: hrvalue null
Before, there was only one child (which is Integer "tmpHR") under the random key, and I have succeeded to retrieve the value. Since I added another child (String Date), the value of tmpHR keeps on returning null.
Any solutions would be appreciated.
Thank you!
Try the following:
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Integer hrValue = dataSnapshot.child("tmpHR").getValue(Integer.class);
showData(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Remove the for loop, since you do not need to loop to be able to retrieve tmpHR in this case.
I have this "chat-system" that I made with Firebase Database.
To retrieve the messages in the Room I do a Query with an orderByChild(timestamp) then reverse the order so I can get the "newest" Last (Because I start reading from the Bottom).
messageList = new ArrayList<>();
final Query query = chatRef_1.orderByChild("
query.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
messageList.add(dataSnapshot.getValue(ChatMessage.class));
updateRecyclerView();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
messageList.remove(dataSnapshot.getValue(ChatMessage.class));
updateRecyclerView();
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
But then I get this result
This only happens with ChildEventListener
The TimeStamp is done by the server
Does anyone have an Idea of what this might be?
UPDATE
Here's the database Structure
Box »» Object (Message)
Green »» MessageID
Blue »» RoomID
This is my database in firebase.
This is my java code for traversing database.
mref = new Firebase("https://social-axxxxxcf.firebaseio.com/user");
mref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
String email=userSnapshot.child("email").getValue().toString();
String urL=userSnapshot.child("url").getKey().toString();
Log.e("Datas= ",email+" " +url);
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("TAG= ",firebaseError.getMessage());
}
});
My problem is when i run this code my app getting crash and even error in log is not showing.
Can anyone help me please.
Since you're using ChildEventListener on /user, your onChildAdded will get called for every node under/user. This means you don't need t loop over dataSnapshot.getChildren():
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String email=dataSnapshot.child("email").getValue(String.classs);
String urL=dataSnapshot.child("url").getValue(String.class);
Log.e("email="+email+" url="+url);
}
Check the following link it's the working example to implement firebase with android.
link
mFirebaseInstance = FirebaseDatabase.getInstance();
mFirebaseRef = mFirebaseInstance.getReferenceFromUrl("https://c7d86.firebaseio.com");
mFirebaseRef.child("bloodgroup").equalTo("B+").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
getUpdate(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
getUpdate(dataSnapshot);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
So please help me because I am a new learner for firebase and have to know how to write a query in this.
Firebase Database queries evaluate the children under the node where you execute the query. So in your case when you use mFirebaseRef.child("bloodgroup") it will look for a /bloodgroup and then query the children under that. Since there is no /bloodgroup, there are no results.
The correct code:
mFirebaseRef = mFirebaseInstance.getReference();
DatabaseReference queryLocation = mFirebaseRef.child("the key under bloodfinder-c7d86 in the screenshot");
Query query = queryLocation.orderByChild("bloodgroup").equalTo("B+");
query.addChildEventListener(new ChildEventListener() {
#Override
Note that I had to do some guesses, because you shared a picture of the JSON. For future questions, share the JSON as text. You can get this by clicking the "Export JSON" link in your Firebase Database console.