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?
Related
I am writing an android app in which I need to retrieve value from Firebase database which I manually added before. The data stored in Firebase database is not symmetrical, which is why I can not use a class object.
I want to do something similar to following codes.
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseRef;
firebaseDatabase = FirebaseDatabase.getInstance();
databaseRef= firebaseDatabase.getReference().child("child").child("child2");
String value = databaseRef.getValue("key");
//In above line I want to retrieve string at child → child2 → key:"value"
While recommended, you don't have to use custom Java classes for getting values out of Firebase. You can also read the primitive types directly, as I'll show below. But no matter whether you use custom classes or primitive types, you will always have to use a listener to read data from the database:
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseRef;
firebaseDatabase = FirebaseDatabase.getInstance();
databaseRef= firebaseDatabase.getReference().child("child").child("child2");
databaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "listener canceled", databaseError.toException());
}
};
You can attach a listener to any level in your JSON tree this way, and Firebase will synchronize all the data below that point into the DataSnapshot. Then you can get it from the snapshot with its getChild() and getValue() methods. So for example to read everything under child, but only print child2:
databaseRef= firebaseDatabase.getReference().child("child");
databaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getChild("child2").getValue(String.class);
Log.i(TAG, "child2: "+value);
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "listener canceled", databaseError.toException());
}
};
The second snippet reads more data from the database, but then only extracts child2 from the snapshot.
You need to set ValueEventListener and take a datasnapshot as written in the Firebase documentation
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
Post post = dataSnapshot.getValue(Post.class);
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
};
mPostReference.addValueEventListener(postListener);
In my Firebase database, I have two children let Child1, Child2. Child1 contains profile information of users as Root/Child1/Uid-User(x)/User_details. Child2 contains transactions done by users as Root/Child2/Uid-User(x)/Transaction_details. I want to retrieve user profile info of one user then transaction of the same user then store it in some object. Then profile info of another user, his transaction and store it in another object and so on.
How can I do that? as Firebase methods run asynchronously so if I create one method to retrieve from Child1 and another for Child2 then they execute asynchronously and create the problem.
You can retrieve it Initially by putting a listener to the userDetail node once this is done ensure retrieved data should not be null after again you make another request to retrive his transction data
Or You Retrieve the both separately and put the result into a 2 HashMap once the data retrieved from both listeners you can merge them based on the key (Ensure that the length of both map should be same)
To ensure Both the listeners are invoked you make like this
Initially put two variables
userProfileHit = 0;
userTransctionHit = 0;
privte void userList () {
userProfileHit ++;
private ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//retriveData
userProfileHit --;
doMergingTask ();
}
#Override
public void onCancelled(DatabaseError databaseError) {
userProfileHit --;
doMergingTask ()
}
};
}
private void transctionList () {
userTransctionHit ++;
private ValueEventListener transctionListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userTransctioneHit --;
doMergingTask ()
}
#Override
public void onCancelled(DatabaseError databaseError) {
userTransctionHit --;
doMergingTask ()
}
};
}
private void doMergingTask () {
if (userTransctionHit == 0 && userProfileHit == 0) {
// Check Datas are valid and merge it
}
}
My suggestion is that you put the method for retrieving the users transactions inside the onDataChanged method for retrieving profile information. So that, when you get the users profile information, you use it to get users transaction information and create the object. You can nest the firebase event listeners to produce the any outcome you want.
For Example:
final FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference ref = database.child("profile");
// Attach the first listener to read the data at our profile reference
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
final Profile profile = dataSnapshot.getValue(Profile.class);
DatabaseReference transactionRef = database.child("transaction");
// Attach a listener to read the data at our transactions reference
transactionRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Transaction transaction = dataSnapshot.getValue(Transaction.class);
//
//Do stuff with the Transaction object and Profile object here.
//
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
I have an android app that reads total number of posts. After that a user writes another post then the total number of post is updated. Also stores post with "postno"+totalPost as the key.
But whenever the operation is performed ,it throws a null-pointer exception on postNo.
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Integer postNo=dataSnapshot.child("posts").getValue(Integer.class);
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference("posts").setValue(postNo+1);
DatabaseReference reference = database.getReference("users/postno" + postNo);
reference.setValue(new Post());
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(MyActivity.this,"Listener Cancelled",Toast.LENGTH_SHORT).show();
}
});
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 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.