I have two tables: friend_lists and users
I want to retrieve data from both. After get data from friend_lists table, I use uidfriend to get data from users. I use two method:
DataSnapshot ds;
private void getPrivateMessages(){
ValueEventListener valueEventListenerPrivateMessage = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.v("data Private message", dataSnapshot.getValue().toString();//it works fine.
ds= dataSnapShot;
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
databaseReferenceFriendLists.child(currentFirebaseUser.getUid()).addValueEventListener(valueEventListenerPrivateMessage);
}
private void getFriendInfo(){
getPrivateMessage();
ValueEventListener valueEventListenerFriendInfo = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.v("data friend info", dataSnapShot.getValue().toString);
Log.v("ds Private Message", ds.getValue().toString());//error: null variable
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
databaseReferenceUsers.addListenerForSingleValueEvent(valueEventListenerFriendInfo);
}
But my app crashed and announced null variable to me. And in logcat, it shown "data friend info" first even though i run getPrivateMessage(); first(it must be "data Private message" first then "data friend info").
What 's wrong in my code? I don't know the way firebase runs.
Related
I am trying to read some values from Firebase Real time database.
My structure looks like this:
and my code to retrieve the value("Wine and Dine"):
databaseReference.child("test").child("event_name").child("drinks")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Object dataSnapshotObject = dataSnapshot.getValue(String.class);
if(dataSnapshotObject != null){
Toast.makeText(content, "Event Name: " + dataSnapshotObject.toString(), Toast.LENGTH_LONG).show();
}else
Toast.makeText(context,"null",Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
});
However, I only get a null response as the value. What could I be doing wrong?
You may remove .child("drinks") from the chain (and put it in later, as in code below)and if you want to make the dataSnapshotObject to String anyway, then you should retrieve it in a String.
Something like this:
String value = dataSnapshot.child("drinks").getValue(String.class);
Also check if your databaseReference looks something like this or not.
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
You can use addListenerForSingleValueEvent to get the value
Code sample:
FirebaseDatabase.getInstance().getReference().child("test").child("event_name").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
HashMap hashUser = (HashMap) dataSnapshot.getValue();
if (hashUser != null) {
String Drinks = hashUser.get("drinks").toString();
//Toast.makeText(this, Drinks , Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
So i have a viewholder which has the name of the user and Under it i wanna put the last message that this user received , i have a query that gives me the last node in the database there is my code :
Query lastQuery = allDb.child("ReceivedMessages").child(mCurrent_user_id).child(list_user_id).orderByKey().limitToLast(1);
lastQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String message = dataSnapshot.child("message").getValue().toString();
friendViewHolder.lastMessage.setText(message);
}
#Override
public void onCancelled(DatabaseError databaseError) {
//Handle possible errors.
}
});
and this is my database structure (also i'm sure that the referance is correct because whenever i assign all of the data to a textView it gives me the last node plus the message and date etc .. but i only want the message )
and this is my error
I hope this will do the job.
Query lastQuery = allDb.child("ReceivedMessages").child(mCurrent_user_id).child(list_user_id).orderByKey().limitToLast(1);
lastQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnaphot.getChildren()) {
String message = ds.child("message").getValue().toString();
friendViewHolder.lastMessage.setText(message);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//Handle possible errors.
}
});
Currently I create a Listing object and store a bunch of fields in there. Two of the fields I need to store are the current User's email and name. I am trying to get those two fields as follows
dbRef = database.getReference().child("Users").child(emailKey);
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserInfo userIn = dataSnapshot.getValue(UserInfo.class);
email1 = userIn.email;
sellerName = userIn.username;
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
After this bit of code I have the line
DatabaseReference temp = dbRefL.push();
temp.setValue(l);
All of this code is called by me pressing a button. The first time I press the button, the entire Listing object is pushed to Firebase just the way I want it EXCEPT the user email and username aren't there because they're blank. The second time I press the button the Strings are there how I want.
My guess is that this is because OnDataChange only executes after I push the Listing object. Is this true? How can I get OnDataChange to execute before I push the listing object?
The listener onDataChange() callbacks are asynchronous. The reason that your email and username is blank is because onDataChange hasn't been executed yet to make sure you push data after email and username are retrieve, put the code inside onDataChange()
dbRef = database.getReference().child("Users").child(emailKey);
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserInfo userIn = dataSnapshot.getValue(UserInfo.class);
email1 = userIn.email;
sellerName = userIn.username;
//set up your l value
DatabaseReference temp = dbRefL.push();
temp.setValue(l);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Once you press the button above code should be called to obtain email and username then push the data as you want.
User addValueEvenListener like :
DatabaseReference map = database.getReference("field_name");
map.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String data = (String) dataSnapshot.getValue();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
****OR using****
database.getReference("field_name").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.e(TAG, "Field data", dataSnapshot.getValue(String.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Failed to read value
Log.e(TAG, "Failed to read user", databaseError.toException());
}
});
I implemented some kind of chat app using Firebase database. Everything is set and working. Now I am trying to implement functionality that after user name changes all his messages with new username. The Message structure looks like this:
I had success whit this code:
private void changeCurrentUserMessagesUserName(final String newUserName) {
mDatabase.child(RequestParameters.FB_CHILD_MESSAGES) //messages
.orderByChild(RequestParameters.FB_CHILD_USERS_UID) //messageUserUid
.equalTo(mUser.getUid())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messageSnapshot : dataSnapshot.getChildren()) {
ChatMessage message = messageSnapshot.getValue(ChatMessage.class);
mDatabase.child(RequestParameters.FB_CHILD_MESSAGES) //messages
.child(message.getMessageNodeKey())
.child(RequestParameters.FB_CHILD_MESSAGES_USERS) //messageUser
.setValue(newUserName);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//do nothing
}
});
}
But it smells, if there are 100 messages in Firebase that belongs to current user this code will make 100 request to Firebase to change "messageUser" node to every single message.
Anyone could help how to make just one request that?
The link Andre provided has the gist of it: by using a single multi-location update, you can send the entire update in one call. Here's the same approach in Java:
mDatabase
.child(RequestParameters.FB_CHILD_MESSAGES) //messages
.orderByChild(RequestParameters.FB_CHILD_USERS_UID)
.equalTo(mUser.getUid())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String,Object> updates = new HashMap<String,Object>();
for (DataSnapshot messageSnapshot : dataSnapshot.getChildren()) {
ChatMessage message = messageSnapshot.getValue(ChatMessage.class);
updates.put(
RequestParameters.FB_CHILD_MESSAGES+"/"+
message.getMessageNodeKey()+"/"+
RequestParameters.FB_CHILD_MESSAGES_USERS,
newUserName
);
}
mDatabase.updateChildren(updates);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
I am printing some custom messages when user clicks on Button, after printing message on Firebase, just closing connection by using database.goOffline(). Here is my code :
private void print() {
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference mainRef = database.getReference("messages");
database.goOnline();
mainRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
database.goOffline();
}
#Override
public void onCancelled(DatabaseError databaseError) {
database.goOffline();
}
});
mainRef.child("abcd").setValue("my message " + randomvalue);
}
It is working for first time by calling print(), but if i am calling it multiple times it just print message for first time, rest of the times it is not doing anything.
Can anyone please provide me solution for that?