I have been trying to retrieve data fields from my firebase database for the past 5 days without any success. This is what my database looks like:
Code for fetching data:
private void alterTextView(final String id) {
if(id!=null) {
mDatabase.child("Users").child(id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserInformation userInformation = dataSnapshot.getValue(UserInformation.class);
String name = (String) userInformation.getName();
Log.d("Main Activity",name);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mWelcomeUserMessage.setText("Welcome, "+name);
}
}`
I have no idea why the name is 'null' (refer to log).
Can someone tell me what I'm doing wrong?
PS: I have defined a blank default constructor, getters, and setters in my UserInformation.java class.
Also, mDatabase is initialized as follows:
mDatabase = FirebaseDatabase.getInstance().getReference();
dataSnapshot.getValue(Class) will only load and set values into public fields. I see you already have a default constructor.
Make name field in UserInformation class public. Also make sure the snapshot you are calling getValue on is a valid JSON representation of UserInformation class and has an exact same "name" field (it must exactly match the name field in class).
Please note:
addValueEventListener adds a listener, which will be called when data is available.
Please note that the data is available after onDataChange has been called. That's why you should set your text right after you get the data you need from the DataSnapshot. Like that:
private void alterTextView(final String id) {
if(id!=null) {
mDatabase.child("Users").child(id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserInformation userInformation = dataSnapshot.getValue(UserInformation.class);
String name = (String) userInformation.getName();
Log.d("Main Activity",name);
runOnUiThread(new Runnable() {
#Override
public void run(){
mWelcomeUserMessage.setText("Welcome, "+name);
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
Related
I'm trying to retrieve the child below "ticket" with the key in between but not able to do it. Method getKey() is return "ticket" instead of the key.
private void getSpecificTicketFromFirebase() {
Timber.d("Inside Pull Data %s ",firebaseManager.getFireBaseUser().getUid()) ;
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("user").child(firebaseManager.getFireBaseUser().getUid()).child("ticket");
FirebaseDatabase.getInstance().getReference().addValueEventListener(new ValueEventListener() {
int i=0;
#Override public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
passengerData = data.getValue(PassengerViewModel.class);
passengerViewModel.add(passengerData);
Timber.d("Passenger Name %s index %s key %s",passengerViewModel.get(i).getFromStationName(),i,data.child("passengerName"));
i++;
}
}
#Override public void onCancelled(DatabaseError databaseError) {
Timber.e(databaseError.getDetails());
Timber.e(databaseError.getMessage());
Timber.e(databaseError.toException());
}
});
}
If you only want to get those objects of PassengerViewModel class, there is no need to use the child() method. Just remove this call: .child(ref.getKey()) and your code will work perfectly fine.
If you want to pass that pushed key to the child() method, you need to store it first into a variable. To achieve this, please use the following code:
String key = ref.push().getKey();
Once you have this key, you can use it in any reference.
First of all Thank you #AlexMamo....
Here is the correct way to do it.....
private void getSpecificTicketFromFirebase() {
DatabaseReference ref =
FirebaseDatabase.getInstance().getReference().child("user").child(firebaseManager.getFireBaseUser().getUid()).child("ticket");
ref.addValueEventListener(new ValueEventListener() {
#Override public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
Timber.d("Key %s",data.getKey());
}
}
#Override public void onCancelled(DatabaseError databaseError) {
Timber.e(databaseError.toException());
}
});
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.
I have this item in the database
And I have a method for removing items, but is not working, this is the method
public void deleteBag(String bagUid, final FirebaseDeleteBaglListener listener) {
Query query = dbReference.child(FirebaseChild.bags.name()).child(bagUid);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
dataSnapshot.getRef().setValue(null);
listener.notifyBagDeleted();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
It gets the reference well, but the method setValue(null) is doing nothing (I've also tried the removeValues().
I don't get any exception or some kind of response, I hope you can help me.
Thanks!
I beleive you have a model class that inserts your items into the database.
so what you have to do is to use that class to reference the object directly and perform the required action on it. Something like this.
public void deleteBag(String bagUid, final FirebaseDeleteBaglListener listener) {
Query query = dbReference.child(FirebaseChild.bags.name()).child(bagUid);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//This shouldn't be there
//dataSnapshot.getRef().setValue(null);
//instead use the modelclass you used inserting data, to reference the object
Modelclass mode = dataSnapshot.getValue(Modelclass.class);
/** Note this line indicates the getter and setter method for the particular object that is being referenced**/
mode.setItem(null)
listener.notifyBagDeleted();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
When you execute a query against the Firebase Database, there will potentially be multiple results. You're using a ValueEventListener, so the snapshot contains a list of all results. Even if there is only a single result, the snapshot will contain a list of one result.
You need to loop over DataSnapshot.getChildren() to get the individual items matching your query:
public void deleteBag(String bagUid, final FirebaseDeleteBaglListener listener) {
Query query = dbReference.child(FirebaseChild.bags.name()).child(bagUid);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
child.getRef().removeValue();
}
listener.notifyBagDeleted();
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
}
I have an ID of User, and i want to take his name from the firebase. So, i am trying to use orderByKey() method to find a certain user and after that, take information from his profile. But something goes wrong ...
reference = FirebaseDatabase.getInstance().getReference("Users");
Query query = reference.orderByKey().equalTo(task.author_id);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
fullName = dataSnapshot.getValue(User.class).getFullName();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Firebase Structure
You don't need a query in that case if you already know the specific path to that node. Just add the listener directly.
reference = FirebaseDatabase.getInstance().getReference("Users");
reference.child(task.author_id).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
fullName = dataSnapshot.getValue(User.class).getFullName();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I am building my first project in android using Firebase.
I have build a Firebase's database which is having main node as post, media as its child node, media node can contain multiple values for a particular post or can have one value inside it.
So i want to fetch media child node values with particular post node.
Could you please help me out.
Any help will deeply appreciated.
Please check the screenshots below.
Firebase ref = new Firebase(YOUR_FIREBASE_URL);
String postNode ="KddShng........";
ref.child("posts/"+postNode).child("media").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.e("!_##_Key : >",dataSnapshot.getKey()); // you will get key of Media node
}
#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) {
}
});
First you need to read docs to know how to retrieve data from firebase.
and your data will be like this ...
final Firebase ref = new Firebase("URL/posts");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
//u can handle your variables name in GetData class
GetData posts = userSnapshot.getValue(GetData.class);
In another way..
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("posts");
String user_id = firebaseAuth.getCurrentUser().getUid();
databaseReference.child(user_id).child("media").getValue("user_id").getValue(etc);
You might save last line as String to reuse it anywhere.
UPDATE:
And to Fitch data You have to use Firebase adapter, example
Try something like this
FirebaseDatabase.getInstance().getReference("posts").child(UID).child("media");
Where UID is the key of the particular post node.
PS: this returns something like a promise, for which you need to attach a listener for. (because this is real time)
If just want to fetch the value once, you can do like this.
FirebaseDatabase.getInstance().getReference("posts").child("your_post_item_id").child("media").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot children : dataSnapshot.getChildren()) {
YourMediaModel mediaItem = children.getValue(YourMediaModel.class);
//add you mediaItem to list that you provided
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}