Retrieve Java Object from Firebase - java

I managed to get the object with this code:
public void retrieveUser(final String email){
firebaseUsersRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
if(messageSnapshot.getKey().equals(Email.encodeID(email))){
retrievedUser = messageSnapshot.getValue(User.class);
break;
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) { }
});
}
(Please note retrievedUser is a class attribute, thus a field.)
I am accessing that field from the code, but even I see it takes the value on the debugger, it is being null on the calling code.
Any hint? CanĀ“t I just return it in the method itself, so it would be?:
public User retrieveUser(final String email);
So, to sum up, how can I return the User object itself?
Thanks

Firebase loads and synchronizes data asynchronously. You can't be sure that your field retrievedUser will have a value when you access it because you don't know when Firebase will call the onDataChange event.
You have to do your work that depends on retrievedUser in the onDataChange event handler like this.
firebaseUsersRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
if(messageSnapshot.getKey().equals(Email.encodeID(email))){
retrievedUser = messageSnapshot.getValue(User.class);
doSomethingWithTheUser(retrievedUser);
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {}
});

You should be able to return the retrievedUser object using a callback or a return statment. Below is some code that shows how to return the value using a callback.
#Override
public void getEvents(final LoadEventsCallback callback) {
final List<Event> events = new ArrayList<Event>();
Firebase ref = new Firebase("https://austin-feeds-me.firebaseio.com/events");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Event event = snapshot.getValue(Event.class);
events.add(event);
}
callback.onEventsLoaded(events);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}

Related

Set a data inside onDataChange method, and use it outside

I'm trying to get name data from Firebase using uid from another collection with an interface, set that data into a variable, and do some task. Then let's say I want to show a Toast if the task is done or not.
This is the method
public void createExcel(final String grade) {
Boolean taskSuccess;
DatabaseReference attendanceRef = FirebaseDatabase.getInstance().getReference().child("attendance").child(grade);
attendanceRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String thisUid;
for (DataSnapshot ds : snapshot.getChildren()) {
for (DataSnapshot ds2 : ds.getChildren()) {
thisUid = ds2.child("uid").getValue().toString();
readData(thisUid, new MyCallBack() {
#Override
public void onCallback(String value) {
thisName[0] = value;
//Do some task
if (//task success) {
taskSuccess == true;
}
}
});
}
}
System.out.println(taskSuccess); //taskSuccess value is always false
}
});
}
This is my interface
public interface MyCallBack {
void onCallback (String value);
}
This is my readData method
public void readData (String uid, final MyCallBack myCallBack) {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("users").child(uid);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String value = snapshot.child("name").getValue().toString();
myCallBack.onCallback(value);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
Is there any way I can set that taskSuccess value inside onDataChange method and use it outside onDataChange method? Because if I make a Toast inside readData it will make some Toasts because of the loop to get the data from database

how to get specific nodes under unique keys in firebase realtime database android

I am trying to get data from nested nodes under unique keys. Each key is identical. It's difficult for me to deal with such problem help please.
I have tried ChildEventListener on database reference but not succeeded.
here is the code i am using to retreive data
InfoFragment.java
auth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance().getReference("Seller").getRef().child("ImpInfo");
mFirebaseDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postDataSnapshot : dataSnapshot.getChildren()) {
ShopSellerInfo shopSellerInfo = postDataSnapshot.getValue(ShopSellerInfo.class);
mShopSellerInfo.add(shopSellerInfo);
}
mNearBySellerAdapter = new NearBySellerAdapter(getContext(), mShopSellerInfo);
mRecyclerView.setAdapter(mNearBySellerAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return rootView;`
ShopSellerInfo.java
public ShopSellerInfo(String shopAddress, String shopPhoneNo, String
shopImageUrl, String shopName) {
this.shopAddress = shopAddress;
this.shopPhoneNo = shopPhoneNo;
this.shopImageUrl = shopImageUrl;
this.shopName = shopName;
}
public ShopSellerInfo() {
}
public String getShopAddress() {
return shopAddress;
}
public String getShopPhoneNo() {
return shopPhoneNo;
}
public String getShopImageUrl() {
return shopImageUrl;
}
public String getShopName() {
return shopName;
}
public void setUserAddress(String shopAddress) {
this.shopAddress = shopAddress;
}
public void setUserPhoneNo(String shopPhoneNo) {
this.shopPhoneNo = shopPhoneNo;
}
public void setImageUrl(String shopImageUrl) {
this.shopImageUrl = shopImageUrl;
}
public void setShopName(String shopName) {
this.shopName = shopName;
}
}
This is the structure of my Database
I have a specific node in each unique key the contain data. I want to retrieve that data form every child node and show on single activity.
You're not too far off, just a few mistakes. The following is closer to what you need:
mFirebaseDatabase = FirebaseDatabase.getInstance().getReference("Seller");
mFirebaseDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot sellerSnapshot : dataSnapshot.getChildren()) {
DataSnapshot impInfoSnapshot = sellerSnapshot.child("ImpInfo");
ShopSellerInfo shopSellerInfo = impInfoSnapshot.getValue(ShopSellerInfo.class);
mShopSellerInfo.add(shopSellerInfo);
mNearBySellerAdapter = new NearBySellerAdapter(getContext(), mShopSellerInfo);
mRecyclerView.setAdapter(mNearBySellerAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
Changes:
Removed the call to .getRef(), which is not needed and in general an anti-pattern.
Removed the call to .child("ImpInfo") from the DatabaseReference, since there is no /Seller/ImpInfo.
Added .child("ImpInfo") in the loop, since you want the ImpInfo child of each snapshot.
Raise an error if onCancelled triggers, since it's a bad practice to ignore errors.

Retrieve the children of a parent node and perform a method on each value

I am building an app that needs to retrieve all child from a certain parent node and would like to perform a method call on each child retrieved.
Here is my current database:
Click Me
I would like to call all child of conradjr and on retrieval of a child for example "ranniecardino15", it should store it to a variable then perform a method call. How can I do this?
I have made a code like this but the method call "getCurrentLocation" is only performed on the last child retrieved.
public void getCurrentChildUser() {
DatabaseReference getuser = FirebaseDatabase.getInstance().getReference().child("Children");
getuser.child(user).orderByChild("CurrentLocation").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
childuser = childSnapshot.getKey();
if (childuser != null){
getCurrentLocation();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public void getCurrentLocation(){
DatabaseReference getuser = FirebaseDatabase.getInstance().getReference().child("Children");
getuser.child(user).child(childuser).child("CurrentLocation").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot != null){
currentloc = dataSnapshot.getValue(String.class);
System.out.println("Current Location: "+currentloc);
String split[] = currentloc.split(",");
lat1 = Double.parseDouble(split[0]);
lng1 = Double.parseDouble(split[1]);
System.out.println("Current Latitude: "+lat1+" and Current Longitude: "+lng1);
getSavedLocation();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
Please help me :) Thanks in advance :)
To solve this, you need to change the declaration of your getCurrentLocation() method from:
public void getCurrentLocation(){}
to
public void getCurrentLocation(String childuser){}
Now you need to call this method from inside the onDataChange() method like this:
getCurrentLocation(childuser);
See, I have passed the childuser as an argument to the getCurrentLocation() so it can be used in a proper way.

How to find if a child with particular value in its fields exists in Firebase?

I need to find if a child with particular value in one of its fields exists in Firebase.
Below is my database structure:
To check if a field exists,you can do this:
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("bdxhATalcDRJCiZZcUFUJo3yrJF2");
ref.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
//then it exists
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
This will check if
child("bdxhATalcDRJCiZZcUFUJo3yrJF2") exists in the database.
If you do this:
ref=FirebaseDatabase.getInstance().getReference().child("bdxhATalcDRJCiZZcUFUJo3yrJF2").orderByChild("chat_id").equalTo(chatid);
then it will check if that child also exists in the database
In your case you would set up query like this:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.orderByChild("chat_id").equalTo("CHAT_ID_To_COMPARE");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot issue : dataSnapshot.getChildren()) {
// do something with the individual object
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This would filter your data at server side and no need to filter data at app side.
postRef = FirebaseDatabase.getInstance().getReference().child("bdxhATalcDRJCiZZcUFUJo3yrJF2");
postRef.orderByChild("chat_id").equalTo(chat_id)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
//bus number exists in Database
} else {
//bus number doesn't exists.
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
etEmail is an EditText
I did it for userEmail's value... as I don't have any username other than the email.
for a structure like this...
"users": {
pushId: {
"userEmail": {
}
}
}
onCreate
etEmail.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
//yourFunction();
DatabaseReference databaseUsers = FirebaseDatabase.getInstance().getReference().child("users");
databaseUsers.orderByChild("userEmail").equalTo(String.valueOf(s))
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot issue : dataSnapshot.getChildren()) {
// do something with the individual object
//User email already exists
//do something
//return; stops the function from executing further
return;
}
} else {
// email doesn't exists.
// do something
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void afterTextChanged(Editable s) {
}
});
When you do the reference and you have your DataSnapshot, you can check it like this:
yourref.child("chat_id").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
//Do something
}
}
exists()
Returns true if the snapshot contains a non-null value.
Also returns true if this DataSnapshot contains any data. It is slightly more efficient than using DataSnapshot.getValue() !== null.

null variables out of onDataChange method

I'm currently developing an android app where I'm using firebase as database but when in got the variable in the onDataChange method and I assign them to a global variables I got null variables but when I call those variables in the onDataChange method they are not null.
public class PositionateMarkerTask extends AsyncTask {
public ArrayList<Location> arrayList= new ArrayList<>();
public void connect() {
//setting connexion parameter
final Firebase ref = new Firebase("https://test.firebaseio.com/test");
Query query = ref.orderByChild("longitude");
//get the data from the DB
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//checking if the user exist
if(dataSnapshot.exists()){
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
//get each user which has the target username
Location location =userSnapshot.getValue(Location.class);
arrayList.add(location);
//if the password is true , the data will be storaged in the sharedPreferences file and a Home activity will be launched
}
}
else{
System.out.println("not found");
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("problem ");
}
});
}
#Override
protected Object doInBackground(Object[] params) {
connect();
return null;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
System.out.println("the firs long is"+arrayList.get(0).getLongitude());
}
}
Even I got the same problem. Just pass the arraylist values inside the onDataChange to another method.
myFirebaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("FIREBASE",String.valueOf(dataSnapshot.getChildrenCount()));
if (dataSnapshot.exists()){
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Log.d("FIREBASE ","FOR LOOP");
//Arraylist codes
iosTitleVal.add(snapshot.getKey().toString());
iosDescVal.add(snapshot.getValue().toString());
Log.d("FIREBASE","ArrayList KEY IS "+iosTitleVal);
//Passing arraylist values to another method
storageContainer(iosTermTitle,iosTermDesc);
}
}else {
Log.d("FIREBASE","NO DATAS");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here's my storageContainer method. In this method I passed the arrraylist values to RecyclerView Adapter's constructor.
public void storageContainer(ArrayList<String> arrayListTitle, ArrayList<String> arrayListDesc){
iosTitleStorage = arrayListTitle;
iosDescStorage = arrayListDesc;
//No null exception here...
Log.d("FIREBASE"," My Data KEY "+iosTitleStorage +" and VAL "+iosDescStorage);
}
I hope it'll work

Categories