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
Related
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
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.
I am trying to fetch data from Firebase database from multiple child in single function. I have two child nodes in Firebase Favorites and Users
I am using RecyclerView to show list of Favorites User but i want to fetch one value name "Online" from Users node.
I add addValueEventListener on Favorites and add addListenerForSingleValueEvent on Users within Favorites addValueEventListener, but my addListenerForSingleValueEvent give null value.
There is my code:
mFavouriteDBRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mList.clear();
if(dataSnapshot.getChildrenCount() > 0){
for(DataSnapshot snap: dataSnapshot.getChildren()){
final Favourites user = snap.getValue(Favourites.class);
final FavouritesList[] holdObj = null;
//if not current user, as we do not want to show ourselves then chat with ourselves lol
try {
if(mAuth.getCurrentUser().getUid().equals(user.getUserId())){
//Firebase Reading data
mUsersDBRef = FirebaseDatabase.getInstance().getReference().child("Users");
mUsersDBRef.child(mAuth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUsersDBRef.child(mAuth.getCurrentUser().getUid()).child("online").onDisconnect().setValue(false);
String local =dataSnapshot.child(mAuth.getCurrentUser().getUid()).child("online").getValue().toString();
if(local.equals("true")){
holdObj[0] = new FavouritesList(mAuth.getCurrentUser().getUid(),user.getFavouriteId(),user.getFavouriteName(),user.getFavouriteCity(),user.getFavouriteCountry(),user.getFavouriteAge(),user.getFavouriteGender(),user.getFavouriteKeyword(),user.getPushKey(), "true","Link");
}else{
holdObj[0] = new FavouritesList(mAuth.getCurrentUser().getUid(),user.getFavouriteId(),user.getFavouriteName(),user.getFavouriteCity(),user.getFavouriteCountry(),user.getFavouriteAge(),user.getFavouriteGender(),user.getFavouriteKeyword(),user.getPushKey(), "false","Link");
}
mList.add(holdObj[0]);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
populaterecyclerView();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here my populaterecyclerView(); Class
private void populaterecyclerView(){
adapter = new UserFavouritesMeHomeListAdapter(context,mList);
adapter.setClickListener(UserFavouritesMeListHomeFragment.this);
recyclerView.setAdapter(adapter);
}
Thanks
Link of Image:
http://userdata.in/singls/images/profile/WobiUh7Zb2bjszmYN0LofK7Pm0z1_20180124042847_file_cover.jpg
Data want to fetch from while reading Favorite
http://userdata.in/singls/images/profile/WobiUh7Zb2bjszmYN0LofK7Pm0z1_20180124044659_file_cover.jpg
cBankRef=myRef.child("user_id").child("ASSETS");
cBankRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.child("1").child("description").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is"+value);
if(dataSnapshot.child("2").exists()) {
String valuess = dataSnapshot.child("3").child("description").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is: " + valuess);
}
if (dataSnapshot.child("3").exists()) {
String values = dataSnapshot.child("1").child("description").getValue(String.class);
Log.d(TAG, "onChildAdded: the cash at bank is: "+values);
}
}
#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(DatabaseError databaseError) {
}
});
first i accessed the user_id child and the ASSETS then through the nodes ("1"),("2") i had to add other nodes in order to get the value, the("1") and ("2") were ("Cash at Bank") ("stock") in the beginning but i decided to change them to numbers but it's giving null #makrand pawar
You have multiple issues in your example:
Your cBankRef is pointing to \user_id\ASSETS\Cash at bank\stock\Cash in Hand, which does not exist (Cash at bank node does not exist under ASSETS).
You are then attaching a ChildEventListener to this reference, which won't return any values, because there aren't any children under it (as it doesn't exist).
Inside onChildAdded(), you are trying to access the houses node which also doesn't exist in your example (house does though).
To access the children under the Stock node, you'll need something like:
ref = FirebaseDatabase.getInstance().getReference().child("user_id").child("ASSETS").child("Stock");
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.child("house").child("values").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is: "+value);
}
// ...
});
The DatabaseReference#child() method is not a SELECT statement. To access everything underneath a node, you only need to create a reference to the highest node required, then attach a listener to that.
For example, if you need access to everything underneath the ASSETS node, you could attach a listener there instead:
ref = FirebaseDatabase.getInstance().getReference().child("user_id").child("ASSETS");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.child("Stock").child("house").child("values").getValue(String.class);
Log.d(TAG, "onChildAdded: the value is: "+value);
if (dataSnapshot.child("Cash at bank").exists()) {
String value = dataSnapshot.child("Cash at bank").getValue(String.class);
Log.d(TAG, "onChildAdded: the cash at bank is: "+value);
}
}
// ...
});
Then when the listener returns you can use DataSnapshot#child() instead to access the individual values retrieved from that location. Also, using DataSnapshot#exists() is a simple way to check that a node exists before using it.
If you plan to have additional values or nodes under ASSETS that don't currently exist, they will be returned by the above listener as soon as they are created.
To achieve this, i suggest you using ValueEventListener like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference stockRef = rootRef.child("user_id").child("ASSETS").child("Stock");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String values = ds.child("house").child("values").getValue(String.class);
Log.d("TAG", values);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
stockRef.addListenerForSingleValueEvent(eventListener);
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) {
}
});
}