Currently, to get the data from the firebase database, I use button to get the data and display them into textview. However, every time i uploaded data, i need to click the button in order to get the data to be displayed.
Therefore, is there a way to display the data right away after the upload session instead of clicking the button to display them?
Below code shows how i display the data at the moment by clicking button which works successfully.
Thanks!
fetch=(Button) v.findViewById(R.id.bFetch_Schedule);
fetch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dayRef.child("Subject").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
textViewSubject_Schedule.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
dayRef.child("What is in our class?").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
textViewWhat_Schedule.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
You need to use addValueEventListener() instead of addListenerForSingleValueEvent().
The listener you provided to addValueEventListener() is called each time the data changes.
The listener you provided to addListenerForSingleValueEvent() is called once with the value of the data at the location.
You may also want to check addChildEventListener(). All information available at the related doc.
You are using addListenerForSingleValueEvent, which gets the value from Firebase and then stops listening. If you use the same code with addValueEventListener it will keep receiving updates.
dayRef.child("Subject").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
textViewSubject_Schedule.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
You'd typically put this code in a lifecycle event of the activity, such as onCreate or onStart.
Related
suppose i am getting data from firebase as
DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
mdb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name=dataSnapshot.child("name").getValue();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//point b
its working perfectly....
if i try to print that string name using
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name=dataSnapshot.child("name").getValue();
System.out.println(name);
}
it will print that string.
but what if i want that string name outside the listener, like in first code where i have added a comment //point b
i tried defining string name globally.
but it only prints the println which is inside onDatachange()... but it will print null at //point b...even if i defined the String name globally.
like
String name;
DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
mdb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
name=dataSnapshot.child("name").getValue();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//point b
edit
actually its a function returning a string value like
public String getData(String id)
{
String name;
DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
mdb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
name=dataSnapshot.child("name").getValue();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return name;
}
Data is loaded from Firebase asynchronously, which unfortunately means that the approach you're trying won't be possible
The easiest way to see this is by simplifying your code to just some log statements:
DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
System.out.println("Before attaching listener");
mdb.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("Inside onDataChange");
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // Don't ignore errors
}
});
System.out.println("After attaching listener");
When you run this code it prints:
Before attaching listener
After attaching listener
Inside onDataChange
That is probably not the output you expected, but explains perfectly why you're not able to return the name from your function: by the time your return statement is executed, the data hasn't been loaded from Firebase yet.
There is no way to wait for the data to come available. Even if there was, it'd lead to your application being blocked and Android displaying the infamous "Application Not Responding" dialog.
Instead you will need to move the code that needs access to the name into the onDataChange method as you've done when printing it.
Also see:
Setting Singleton property value in Firebase Listener
can't get values out of ondatachange method
Firebase/Android: Adding retrieved values from Firebase to arraylist returns null pointer exception
You can't access the variable outside the onDataChange. So if you want to access the variable maybe for function/method you can implement the method inside the onDataChange. As the onDataChange will be the one running last. So make sure anything relating to the variable being done inside the onDataChange.
private FirebaseAuth firebaseAuth=FirebaseAuth.getInstance();;
private FirebaseUser firebaseUser=firebaseAuth.getCurrentUser();
/******************************After declaration**************************************/
userIDDatabaseReference=FirebaseDatabase.getInstance().getReference("login");
userIDDatabaseReference.child(firebaseUser.getUid()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.w("Show out:", "In Firebase ValueEventListener");
LoginClass tempClass=dataSnapshot.getValue(LoginClass.class);
loginID=tempClass.getLoginID();
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("Database Error: "+databaseError.getDetails());
}
});
above is my coding, I wanna retrieve loginID but my event listener does not fire as the log.w did't not print any log in my logcat, I think my function does not trigger the onDataChange() because every time it will return null for the loginID. Can someone tell me what am I missing?? I referred to all documentation related, I really don't figure out what is the problem over here.
thank you~~
Use a single value event listener to get the data one time. Use this code:
userIDDatabaseReference.child(firebaseUser.getUid()).addSingleValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.w("Show out:", "In Firebase ValueEventListener");
LoginClass tempClass=dataSnapshot.getValue(LoginClass.class);
loginID=tempClass.getLoginID();
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("Database Error: "+databaseError.getDetails());
}
});
Hey I am trying to get the current TIMESTAMP in the app when clicking a button but the TIMESTAMP is incorrect. The TIMESTAMP sometimes shows the time ahead and sometimes 10 minutes before time. Here is the code
timestapmReference.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
final long timeStampLong = (long) dataSnapshot.child("time").child("timestampQuestionSeen").getValue();
final DatabaseReference questionSeenReference = FirebaseDatabase.getInstance().getReference().child("users").child(uid).child("questions").
child(imagename);
questionSeenReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.hasChild("questionSeen")) {
questionSeenReference.child("questionSeenTime").setValue(timeStampLong);
questionSeenReference.child("questionSeen").setValue("1");
}
questionSeenReference.removeEventListener(this);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
timestapmReference.removeEventListener(this);
}
public void onCancelled(DatabaseError databaseError) {
}
});
timestapmReference.child("time").child("timestampQuestionSeen").setValue(ServerValue.TIMESTAMP);
Your problem is that you are setting those values insider the onDataChange method. There is no need to do such a thing. Move this 2 lines:
questionSeenReference.child("questionSeenTime").setValue(timeStampLong);
questionSeenReference.child("questionSeen").setValue("1");
outside that method and remove that listener because is useless. To set a value you only need to use the setValue() method directly on the reference.
Hope it helps.
I am working on an android application, using Firebase and Android Studio.
I had issues with retrieving values with value event listeners because i couldnt set values inside the onDataChange method to be used else where because it runs asynchronously, so the listener may or may not have completed its purpose before the value is needed outside. So I solved this issue by putting whatever needs to be done inside the onDataChange method(real life saver!).
But
the value i am retrieving in the onDataChange also happens to be needed inside another listener. like this
DatabaseReference mLastnameReference = rootRef.child("users").child("12345678").child(phone);
ValueEventListener lastnameListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
yourid = dataSnapshot.getValue().toString();
}
catch (NullPointerException e){
//handle user not registered here
}
DatabaseReference mBioReference = FirebaseDatabase.getInstance().getReference().child("users").child(yourid).child("status");
ValueEventListener bioListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Status = dataSnapshot.getValue().toString();
mTextField = (TextView) findViewById(R.id.status);
mTextField.setText(Status);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
mBioReference.addValueEventListener(bioListener);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
mLastnameReference.addValueEventListener(lastnameListener);
the value im waiting for in the first listener is yourid . I also need that value to get a database reference to the node for the nested listener to be executed. But when i ran this code, both of them appear to be running at the same time. Hence, getting a null exception on the nested database reference, because the yourid appears to not have been retrieved at that time.
In the code you shared, the value of users/12345678/$phone will be read before you attach the nested listener. But the value might be null, which you code doesn't handle correctly:
DatabaseReference mLastnameReference = rootRef.child("users").child("12345678").child(phone);
ValueEventListener lastnameListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String id = String.valueOf(dataSnapshot.getValue());
if (id != null) {
DatabaseReference mBioReference = FirebaseDatabase.getInstance().getReference().child("users").child(id).child("status");
ValueEventListener bioListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Status = dataSnapshot.getValue(String.class);
mTextField = (TextView) findViewById(R.id.status);
mTextField.setText(Status);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
};
mBioReference.addValueEventListener(bioListener);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
};
mLastnameReference.addValueEventListener(lastnameListener);
I've replaced the try-catch with a regular if and made id a local variable, which removes the chance that some other part of your code sets it to null. It also throw exceptions in onCancelled now, since it's best to not ignore those authorization problems.
I wanted to create an application that uses firebase as a backend.Now the problem I have is that I have to attach a listener to get back a snapshot of data. But for every time my application starts,I want to query firebase for data and populate my views even though there has been no change in the database.
I suppose you are doing something like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Code
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Code
}
});
So for what I think you're asking, calling an alternative method called addListenerForSingleValueEvent should solve the problem. It will not listen for changes, as soon as returns a value, it will stop connecting until being attached again.
Result
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Code
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Code
}
});