public List<String> getContactsFromFirebase(){
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
Log.i("Test", mContactsFromFirebase.toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return mContactsFromFirebase;
}
I can't seem to find the error. In the code above, when I call the log, I get the values from mContactsFromFirebase, but the getContactsFromFirebase() method return an empty list. Could you help me please?
Data is loaded from Firebase asynchronously. Since it may take some time to get the data from the server, the main Android code continues and Firebase calls your onDataChange when the data is available.
This means that by the time you return mContactsFromFirebase it is still empty. The easiest way to see this is by placing a few log statements:
System.out.println("Before attaching listener");
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("In 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 will print:
Before attaching listener
After attaching listener
In onDataChange
That is probably not the order that you expected the output in. As you can see the line after the callback gets called before onDataChange. That explains why the list you return is empty, or (more correctly) it is empty when you return it and only gets filled later.
There are a few ways of dealing with this asynchronous loading.
The simplest to explain is to put all code that returns the list into the onDataChange method. That means that this code is only execute after the data has been loaded. In its simplest form:
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
}
But there are more approaches including using a custom callback (similar to Firebase's own ValueEventListener):
Java:
public interface UserListCallback {
void onCallback(List<Users> value);
}
Kotlin:
interface UserListCallback {
fun onCallback(value:List<Users>)
}
Now you can pass in an implementation of this interface to your getContactsFromFirebase method:
Java:
public void getContactsFromFirebase(final UserListCallback myCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
myCallback.onCallback(mContactsFromFirebase);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
Kotlin:
fun getContactsFromFirebase(myCallback:UserListCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(object:ValueEventListener() {
fun onDataChange(dataSnapshot:DataSnapshot) {
for (snapshot in dataSnapshot.getChildren())
{
val user = snapshot.getValue(Users::class.java)
assert(user != null)
val contact_found = user.getPhone_number()
mContactsFromFirebase.add(contact_found)
System.out.println("Loaded " + mContactsFromFirebase.size() + " contacts")
}
myCallback.onCallback(mContactsFromFirebase)
}
fun onCancelled(databaseError:DatabaseError) {
throw databaseError.toException()
}
})
And then call it like this:
Java:
getContactsFromFirebase(new UserListCallback() {
#Override
public void onCallback(List<Users> users) {
System.out.println("Loaded "+users.size()+" contacts")
}
});
Kotlin:
getContactsFromFirebase(object:UserListCallback() {
fun onCallback(users:List<Users>) {
System.out.println("Loaded " + users.size() + " contacts")
}
})
It's not as simple as when data is loaded synchronously, but this has the advantage that it runs without blocking your main thread.
This topic has been discussed a lot before, so I recommend you check out some of these questions too:
this blog post from Doug
Setting Singleton property value in Firebase Listener (where I explained how in some cases you can get synchronous data loading, but usually can't)
return an object Android (the first time I used the log statements to explain what's going on)
Is it possible to synchronously load data from Firebase?
https://stackoverflow.com/a/38188683 (where Doug shows a cool-but-complex way of using the Task API with Firebase Database)
How to return DataSnapshot value as a result of a method? (from where I borrowed some of the callback syntax)
Related
public List<String> getContactsFromFirebase(){
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
Log.i("Test", mContactsFromFirebase.toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return mContactsFromFirebase;
}
I can't seem to find the error. In the code above, when I call the log, I get the values from mContactsFromFirebase, but the getContactsFromFirebase() method return an empty list. Could you help me please?
Data is loaded from Firebase asynchronously. Since it may take some time to get the data from the server, the main Android code continues and Firebase calls your onDataChange when the data is available.
This means that by the time you return mContactsFromFirebase it is still empty. The easiest way to see this is by placing a few log statements:
System.out.println("Before attaching listener");
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("In 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 will print:
Before attaching listener
After attaching listener
In onDataChange
That is probably not the order that you expected the output in. As you can see the line after the callback gets called before onDataChange. That explains why the list you return is empty, or (more correctly) it is empty when you return it and only gets filled later.
There are a few ways of dealing with this asynchronous loading.
The simplest to explain is to put all code that returns the list into the onDataChange method. That means that this code is only execute after the data has been loaded. In its simplest form:
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
}
But there are more approaches including using a custom callback (similar to Firebase's own ValueEventListener):
Java:
public interface UserListCallback {
void onCallback(List<Users> value);
}
Kotlin:
interface UserListCallback {
fun onCallback(value:List<Users>)
}
Now you can pass in an implementation of this interface to your getContactsFromFirebase method:
Java:
public void getContactsFromFirebase(final UserListCallback myCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
myCallback.onCallback(mContactsFromFirebase);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
Kotlin:
fun getContactsFromFirebase(myCallback:UserListCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(object:ValueEventListener() {
fun onDataChange(dataSnapshot:DataSnapshot) {
for (snapshot in dataSnapshot.getChildren())
{
val user = snapshot.getValue(Users::class.java)
assert(user != null)
val contact_found = user.getPhone_number()
mContactsFromFirebase.add(contact_found)
System.out.println("Loaded " + mContactsFromFirebase.size() + " contacts")
}
myCallback.onCallback(mContactsFromFirebase)
}
fun onCancelled(databaseError:DatabaseError) {
throw databaseError.toException()
}
})
And then call it like this:
Java:
getContactsFromFirebase(new UserListCallback() {
#Override
public void onCallback(List<Users> users) {
System.out.println("Loaded "+users.size()+" contacts")
}
});
Kotlin:
getContactsFromFirebase(object:UserListCallback() {
fun onCallback(users:List<Users>) {
System.out.println("Loaded " + users.size() + " contacts")
}
})
It's not as simple as when data is loaded synchronously, but this has the advantage that it runs without blocking your main thread.
This topic has been discussed a lot before, so I recommend you check out some of these questions too:
this blog post from Doug
Setting Singleton property value in Firebase Listener (where I explained how in some cases you can get synchronous data loading, but usually can't)
return an object Android (the first time I used the log statements to explain what's going on)
Is it possible to synchronously load data from Firebase?
https://stackoverflow.com/a/38188683 (where Doug shows a cool-but-complex way of using the Task API with Firebase Database)
How to return DataSnapshot value as a result of a method? (from where I borrowed some of the callback syntax)
public List<String> getContactsFromFirebase(){
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
Log.i("Test", mContactsFromFirebase.toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return mContactsFromFirebase;
}
I can't seem to find the error. In the code above, when I call the log, I get the values from mContactsFromFirebase, but the getContactsFromFirebase() method return an empty list. Could you help me please?
Data is loaded from Firebase asynchronously. Since it may take some time to get the data from the server, the main Android code continues and Firebase calls your onDataChange when the data is available.
This means that by the time you return mContactsFromFirebase it is still empty. The easiest way to see this is by placing a few log statements:
System.out.println("Before attaching listener");
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("In 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 will print:
Before attaching listener
After attaching listener
In onDataChange
That is probably not the order that you expected the output in. As you can see the line after the callback gets called before onDataChange. That explains why the list you return is empty, or (more correctly) it is empty when you return it and only gets filled later.
There are a few ways of dealing with this asynchronous loading.
The simplest to explain is to put all code that returns the list into the onDataChange method. That means that this code is only execute after the data has been loaded. In its simplest form:
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
}
But there are more approaches including using a custom callback (similar to Firebase's own ValueEventListener):
Java:
public interface UserListCallback {
void onCallback(List<Users> value);
}
Kotlin:
interface UserListCallback {
fun onCallback(value:List<Users>)
}
Now you can pass in an implementation of this interface to your getContactsFromFirebase method:
Java:
public void getContactsFromFirebase(final UserListCallback myCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
myCallback.onCallback(mContactsFromFirebase);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
Kotlin:
fun getContactsFromFirebase(myCallback:UserListCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(object:ValueEventListener() {
fun onDataChange(dataSnapshot:DataSnapshot) {
for (snapshot in dataSnapshot.getChildren())
{
val user = snapshot.getValue(Users::class.java)
assert(user != null)
val contact_found = user.getPhone_number()
mContactsFromFirebase.add(contact_found)
System.out.println("Loaded " + mContactsFromFirebase.size() + " contacts")
}
myCallback.onCallback(mContactsFromFirebase)
}
fun onCancelled(databaseError:DatabaseError) {
throw databaseError.toException()
}
})
And then call it like this:
Java:
getContactsFromFirebase(new UserListCallback() {
#Override
public void onCallback(List<Users> users) {
System.out.println("Loaded "+users.size()+" contacts")
}
});
Kotlin:
getContactsFromFirebase(object:UserListCallback() {
fun onCallback(users:List<Users>) {
System.out.println("Loaded " + users.size() + " contacts")
}
})
It's not as simple as when data is loaded synchronously, but this has the advantage that it runs without blocking your main thread.
This topic has been discussed a lot before, so I recommend you check out some of these questions too:
this blog post from Doug
Setting Singleton property value in Firebase Listener (where I explained how in some cases you can get synchronous data loading, but usually can't)
return an object Android (the first time I used the log statements to explain what's going on)
Is it possible to synchronously load data from Firebase?
https://stackoverflow.com/a/38188683 (where Doug shows a cool-but-complex way of using the Task API with Firebase Database)
How to return DataSnapshot value as a result of a method? (from where I borrowed some of the callback syntax)
public List<String> getContactsFromFirebase(){
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
Log.i("Test", mContactsFromFirebase.toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return mContactsFromFirebase;
}
I can't seem to find the error. In the code above, when I call the log, I get the values from mContactsFromFirebase, but the getContactsFromFirebase() method return an empty list. Could you help me please?
Data is loaded from Firebase asynchronously. Since it may take some time to get the data from the server, the main Android code continues and Firebase calls your onDataChange when the data is available.
This means that by the time you return mContactsFromFirebase it is still empty. The easiest way to see this is by placing a few log statements:
System.out.println("Before attaching listener");
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("In 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 will print:
Before attaching listener
After attaching listener
In onDataChange
That is probably not the order that you expected the output in. As you can see the line after the callback gets called before onDataChange. That explains why the list you return is empty, or (more correctly) it is empty when you return it and only gets filled later.
There are a few ways of dealing with this asynchronous loading.
The simplest to explain is to put all code that returns the list into the onDataChange method. That means that this code is only execute after the data has been loaded. In its simplest form:
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
}
But there are more approaches including using a custom callback (similar to Firebase's own ValueEventListener):
Java:
public interface UserListCallback {
void onCallback(List<Users> value);
}
Kotlin:
interface UserListCallback {
fun onCallback(value:List<Users>)
}
Now you can pass in an implementation of this interface to your getContactsFromFirebase method:
Java:
public void getContactsFromFirebase(final UserListCallback myCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
}
myCallback.onCallback(mContactsFromFirebase);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
Kotlin:
fun getContactsFromFirebase(myCallback:UserListCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(object:ValueEventListener() {
fun onDataChange(dataSnapshot:DataSnapshot) {
for (snapshot in dataSnapshot.getChildren())
{
val user = snapshot.getValue(Users::class.java)
assert(user != null)
val contact_found = user.getPhone_number()
mContactsFromFirebase.add(contact_found)
System.out.println("Loaded " + mContactsFromFirebase.size() + " contacts")
}
myCallback.onCallback(mContactsFromFirebase)
}
fun onCancelled(databaseError:DatabaseError) {
throw databaseError.toException()
}
})
And then call it like this:
Java:
getContactsFromFirebase(new UserListCallback() {
#Override
public void onCallback(List<Users> users) {
System.out.println("Loaded "+users.size()+" contacts")
}
});
Kotlin:
getContactsFromFirebase(object:UserListCallback() {
fun onCallback(users:List<Users>) {
System.out.println("Loaded " + users.size() + " contacts")
}
})
It's not as simple as when data is loaded synchronously, but this has the advantage that it runs without blocking your main thread.
This topic has been discussed a lot before, so I recommend you check out some of these questions too:
this blog post from Doug
Setting Singleton property value in Firebase Listener (where I explained how in some cases you can get synchronous data loading, but usually can't)
return an object Android (the first time I used the log statements to explain what's going on)
Is it possible to synchronously load data from Firebase?
https://stackoverflow.com/a/38188683 (where Doug shows a cool-but-complex way of using the Task API with Firebase Database)
How to return DataSnapshot value as a result of a method? (from where I borrowed some of the callback syntax)
Hello I create a small social network for my high school and I use android studio and firebase as server for the data.My database structure for Users info - / (Users)
- /James/
–- /james-uid/
- /David/
–- /james-uid/
I added the possibility of blocking users. My database is structured
- / (root)
- /UsersIblocked/
–- /james-uid/
-- /jake-uid/
-- /David-uid/
-- /Karl-uid/
, now I would like that when my application displays posts that the publications of the users that we blocked does not appear .
to make the publications appear I use this code ( This code should take the uid of the person who posted the post and see if this uid is in our blocked list and if there is, it should not take the post)
mAuth = FirebaseAuth.getInstance();
ArrayList<PostClass> PostArray= new ArrayList<>();
Listview = new PostAdapter(getActivity(),R.layout.itempost, PostArray );
mDatabase = FirebaseDatabase.getInstance().getReference().child("Blog");
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Log.d(TAG, "getPost: found post user: " + snapshot);
PostClass post = snapshot.getValue(PostClass.class);
DatabaseReference blockDatabase = FirebaseDatabase.getInstance().getReference().child("BlockedUsers").child("UsersIBlocked").child(mAuth.getCurrentUser().getUid());
blockDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.child(post.getuid).exists()){
PostArray.add(post);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Collections.reverse(PostArray);
Listview.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Post is the class that I use to receive the data on the publication, post.getuid gives me the uid of the person who published the publication
But nothing happens when I use this code, so if someone can help me thank you
You should call Listview.notifyDataSetChanged(); whenever the data set of the list view has changed. Since you're loading data in a nested addListenerForSingleValueEvent, you should call it in the onDataChange() of that listener:
blockDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.child(post.getuid).exists()){
PostArray.add(post);
Listview.notifyDataSetChanged();
}
}
...
Also note that it's a really bad practice to leave onCancelled empty, as it hides potential problems. The simplest implementation is:
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
Query sqlite = mDatabaseReference.child("Messages").child(MessageSenderId).child(MessageRecieverId);
sqlite.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("Message")) {
String msg = dataSnapshot.child("Message").getValue().toString();
String from = dataSnapshot.child("From").getValue().toString();
String time = dataSnapshot.child("Time").getValue().toString();
} else {
Toast.makeText(getApplicationContext(), "NULLLL", Toast.LENGTH_SHORT).show();
}
Database
This is the most basic thing in the database. I have never got a problem with childEvent or valueEvent and i want a single event for now and I'm not able to fetch.
There is no error because i have put an if statement and it shows toast as null which means dataSnapshot doesn't have a child named messages but it's right there. I tried putting a for loop too, but didn't work
You have not given the full reference. There is a list of push keys and you have to use a foreach loop.
Query sqlite = mDatabaseReference.child("Messages").child(MessageSenderId).child(MessageRecieverId);
sqlite.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot vinSnapshot : dataSnapshot.getChildren()) {
if (vinSnapshot .hasChild("Message")) {
String msg = dataSnapshot.child("Message").getValue().toString();
String from = dataSnapshot.child("From").getValue().toString();
String time = dataSnapshot.child("Time").getValue().toString();
} else {
Toast.makeText(getApplicationContext(), "NULLLL", Toast.LENGTH_SHORT).show();
}
}
Or you can store all data into ArrayList then perform your task.