Extract child's name from DatabaseReference in Google Firebase - android

I want to extract the names (strings) of all the childs of mUsrRef.
DatabaseReference mUsrRef;
public void read_child() {
mUsrRef = mUsersRef.child("user_name");
// ...
}
How can I do it?

You can use DataSnapshot.getChildren() for that:
public void read_child() {
mUsrRef = mUsersRef.child("user_name");
mUsrRef.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
Log.i(TAG, childSnapshot.getKey());
}
}
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "onCancelled", databaseError.toException());
}
});
}

You must add a listener. For instance :
mUsrRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren() ) {
child.getKey();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope this helps.

Related

Retrieve the IDs of a user's friends and show in RecyclerView the data of each friend (Firebase)

In the Firebase, I have a “usuario” node with the data for each registered user. I want to retrieve the Ids of a user's friends and through these ID's show in RecyclerView the data of each friend (identifier, name and photo address).
My structure in Firebase:
I tried this code, but it doesn't work. the list is empty:
ref = ConfigFirebase.getFirebaseDatabase().child("usuarios"); //code in OnCreate
//My method
ref = ref.child(idUserLog).child("friends");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot idFriends: dataSnapshot.getChildren()){
DataUserFriend dataUserFriend = idFriends.getValue(DataUserFriend.class);
String id = dataUserFriend.getIdUser();
ref.child(id).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
DataUser dataUser = dataSnapshot.getValue(DataUser.class);
listFriends.add(dataUser);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
listFriendsAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
What is wrong? or should i try another way?
Solution:
ref = ConfigFirebase.getFirebaseDatabase().child("usuarios"); //code in OnCreate
//My method
ref = ref.child(idUserLog).child("friends");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final int numFriends = (int) dataSnapshot.getChildrenCount();
if(numFriends != 0){
for (DataSnapshot idFriends: dataSnapshot.getChildren()){
DataUserFriend dataUserFriend = idFriends.getValue(DataUserFriend.class);
String id = dataUserFriend.getIdUser();
ref = ConfigFirebase.getFirebaseDatabase().child("usuarios").child(id);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
DataUser dataUser = dataSnapshot.getValue(DataUser.class);
listFriends.add(dataUser);
if(listFriends.size() == numFriends){
listFriendsAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
The call to listFriendsAdapter.notifyDataSetChanged() should happen in the same method that updates listFriends.
So:
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot idFriends: dataSnapshot.getChildren()){
DataUserFriend dataUserFriend = idFriends.getValue(DataUserFriend.class);
String id = dataUserFriend.getIdUser();
ref.child(id).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
DataUser dataUser = dataSnapshot.getValue(DataUser.class);
listFriends.add(dataUser);
listFriendsAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
If you want to call listFriendsAdapter.notifyDataSetChanged() only when all friends have been added to listFriends, you can keep a count of how often the inner onDataChange has been called and compare that to the number of friend IDs.
You have added SingleValueEvent listener on database reference object due to which the callback isn't getting fired immediately. You should create a Query and add the SingleValueEvent listener for it. For example:
DatabaseReference mDatabase;
mDatabase = FirebaseDatabase.getInstance().getReference("usuarios");
Query query = mDatabase.child(idUserLog).child("friends");
query .addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// Code to parse and display data
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

get all data and insert to arraylist from firebase

i wanto get all color data from firebase then insert to arraylist, and the color data structure like image below
and here is when i want to insert to Arraylist
private void getDataDetailProduct() {
imageReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
for (DataSnapshot childSbapshot : dataSnapshot.getChildren()){
String id = childSbapshot.getKey();
ArrayList<String>images = new ArrayList<>();
images.add(String.valueOf(childSbapshot.getChildren()));
}
initSlideImage();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
ArrayList<String>images = new ArrayList<>();
private void getDataDetailProduct() {
imageReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
for (DataSnapshot childSbapshot : dataSnapshot.getChildren()){
String id = childSbapshot.getKey();
images.add(String.valueOf(childSbapshot.child("colors1").getValue()));
images.add(String.valueOf(childSbapshot.child("colors2").getValue()));
images.add(String.valueOf(childSbapshot.child("colors3").getValue()));
}
initSlideImage();
}}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}

How to execute firebase function synchronously inside for loop?

I am retrieving data from firebase database inside for loop , but problem is that firebase functions are not execute synchronously , i know firebase functions are asynchronous . is there any solution for that ?
Code :-
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModelList.clear();
for(DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
Log.d("kkkk","1st");
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
peopleModelList.add(peopleModel);
Log.d("kkkk","2nd");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Log.d("kkkk","3rd");
}
iCallBackPeople.peopleAct(peopleModelList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Output :-
1st
3rd
2nd
But i want output like this
1st
2nd
3rd
Note :-
i searched , but never got any solution !
How to get data from Firebase Database in a loop?
Firebase addListenerForSingleValueEvent excute later in loop
I tried this but not worked for me, it is fill my list with last item !
public void listOfUsers(final ICallBackPeople iCallBackPeople) {
count=0;
//peopleModelList = new ArrayList<>();
sortedMap = new TreeMap<>();
// peopleModelList = new ArrayList<PeopleModel>(sortedMap.values());
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// peopleModelList.clear();
for(DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
//Object chatRoom = snapshot.getKey();
Log.d("kkkk","1st");
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
addItem(count,iCallBackPeople);
count++;
}
Log.d("kkkk","3rd");
}
Log.d("kkkk","end");
//iCallBackPeople.peopleAct(peopleModelList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void addItem(final int index, final ICallBackPeople iCallBackPeople) {
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
Log.d("kkkk","2nd");
sortedMap.put(index, peopleModel);
// sortedMap will sort your list by key (in this case, key is integer)
if(sortedMap.size()==2)
{
peopleModelList = new ArrayList<PeopleModel>(sortedMap.values());
iCallBackPeople.peopleAct(peopleModelList);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I tried this but not getting all of the item only getting list with last item in snapshot
public void listOfUsers(final ICallBackPeople iCallBackPeople) {
peopleModelList = new ArrayList<>();
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
PeopleModel peopleModel;
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModelList.clear();
for(final DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
getToken(new CallBackGetToken() {
#Override
public void token(String token) {
peopleModel.setRefresh_token(token);
Toast.makeText(context, token, Toast.LENGTH_SHORT).show();
peopleModelList.add(peopleModel);
//here i am checking my peopleModelList size is equal or not to snapshot
if(peopleModelList.size()==2)
iCallBackPeople.peopleAct(peopleModelList);
}
},peopleModel);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void getToken(final CallBackGetToken callBackGetToken ,PeopleModel peopleModel) {
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
callBackGetToken.token((String)dataSnapshot.child("refresh_token").getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I think you should pass through an interface(create one and implement at this class). the method inside the interface should have a string as a parameter (it will receive your peopleModel.getChatWith() ) .
Inside your if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))you should request your interface.
I think is a solution for your asynchronously question.
Here is my solution:
int count =0;
SortedMap<Integer,PeopleModel> sortedMap;
private void set() {
count =0;
registrationReference.child(userId).child("generated_links").addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModelList.clear();
sortedMap = new TreeMap<>();
for(DataSnapshot snapshot : dataSnapshot.getChildren())
{
peopleModel = new PeopleModel();
peopleHashMap =(HashMap)snapshot.getValue();
peopleModel.setChatWith((String)peopleHashMap.get("chatWith"));
peopleModel.setNickname((String)peopleHashMap.get("nickname"));
peopleModel.setChatRoom(snapshot.getKey());
Log.d("kkkk","1st");
if(peopleModel.getChatWith()!=null && !("".equals(peopleModel.getChatWith())))
{
addItem(count);
count++;
}
Log.d("kkkk","3rd");
}
iCallBackPeople.peopleAct(peopleModelList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void addItem(final int index) {
registrationReference.child(peopleModel.getChatWith()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
peopleModel.setRefresh_token((String)dataSnapshot.child("refresh_token").getValue());
Log.d("kkkk","2nd");
sortedMap.put(index, peopleModel);
// sortedMap will sort your list by key (in this case, key is integer)
// you can get peopleModelList = new ArrayList<>(sortedMap.values);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Maybe I'm over simplifying it, but I feel like you should just use simple recursion.
List<People> peopleList;
int currentIndex = 0
private void myFirebaseMethodAction(person){
registerListener.onCallbacks(new ValueListener(){
onDataChanged(){
person.addStufforDoStuff();
if(peopleList.size > currentIndex + 1){
myFirebaseMethodAction(peopleList.get(++currentIndex)
}
}
onFailed(){
//handle it
}
}
}
Does that make sense?
Just saying walk the list with an index, simple.
btw above is pseduo code, don't copy verbatim lol.

How to use multiple orederbychild in Firebase database?

Hello Everyone I am using firebase database in my app. I am able to add data to database. Now I want to implement search in my app, I have two option for search users,
1)Blood Group
2)User Area
I am able to get data as per blood group selection, but I don't know how can I fetch data with blood group and area. (Multiple Selection Filter)
Now if the user will select 'A+' as blood group from spinner and select Area 'ABC'
Then result would come as Users with 'A+' blood group and 'ABC' area.
search_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("Default Selected"+sel_blood_group);
mFirebaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Your Logic here
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
UserRegisterModel mModel = eventSnapshot.getValue(UserRegisterModel.class);
// Log.e("DATA" ,""+ mModel.getName());
}
Query chatRoomsQuery = mFirebaseDatabase.orderByChild("blood_group").equalTo(sel_blood_group);
chatRoomsQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// dataSnapshot is the "issue" node with all children with id 0
for (DataSnapshot issue : dataSnapshot.getChildren()) {
// do something with the individual "issues"
UserRegisterModel mModel = issue.getValue(UserRegisterModel.class);
Log.e("QUERY DATA" ,""+ mModel.getName());
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Log.e("DATA" ,""+ chatRoomsQuery.toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
Firebase RealTime Database does not support multiple where clauses. So try to query with one filter and then filter the next one programatically.
search_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("Default Selected"+sel_blood_group);
System.out.println("Default Selected"+sel_area);
mFirebaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Your Logic here
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
UserRegisterModel mModel = eventSnapshot.getValue(UserRegisterModel.class);
// Log.e("DATA" ,""+ mModel.getName());
}
Query chatRoomsQuery = mFirebaseDatabase.orderByChild("blood_group").equalTo(sel_blood_group);
chatRoomsQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// dataSnapshot is the "issue" node with all children with id 0
for (DataSnapshot issue : dataSnapshot.getChildren()) {
// do something with the individual "issues"
UserRegisterModel mModel = issue.getValue(UserRegisterModel.class);
if(mModel.getArea().equals(sel_area))
Log.e("QUERY DATA" ,""+ mModel.getName());
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Log.e("DATA" ,""+ chatRoomsQuery.toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});enter code here
You can make userName to be added only once using the following method. I have assumed that you are storing the user details in UserRegisterModel class. Please take care of the DatabaseReferences as I have used what you have mentioned and I am not aware of your Database structure.
Query chatRoomsQuery = mFirebaseDatabase.orderByChild("User_Name").equalTo(userRegisterModel.getUserName());
chatRoomsQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Log.e("UserAlready Registered");
}
else
{
mFirebaseDatabase.push().setValue(userRegisterModel);;
Log.i("User added Successfully");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I have not tested the code but I think it will work! :)

Make sure that all Firebase single ValueEventsListeners finished

As mentioned in docs, it's better to fetch additional data, than nest objects in database.
According to this, how can I ensure that all data came?
I came up to this solution, but I'm not sure if this will work.
mPetsReference.addValueEventListener(new ValueEventListener() {
private List<Pair<Pet, Owner>> mData;
private long mChildrenCount;
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mData = new ArrayList<>();
mChildrenCount = dataSnapshot.getChildrenCount();
for (DataSnapshot data : dataSnapshot.getChildren()) {
Pet pet = data.getValue(Pet.class);
mOwnersReference.child(pet.getOwnerId())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mData.add(new Pair<>(pet, dataSnapshot.getValue(Owner.class)));
if (mData.size() == mChildrenCount) {
everythingCame();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
mChildrenCount--;
if (mData.size() == mChildrenCount) {
everythingCame();
}
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Categories

Resources