Firebase nested ValueEventListener - android

I have the following database structure -
{
"linking" : {
"shift-assign" : { // for every shift its assigned users
"key1" : {
"111" : true,
"222" : true
},
"key2" : {
"111" : true
}
},
"user-assign" : { // for every user its assigned shifts
"111" : {
"key1" : true,
"key2" : true
},
"222" : {
"key1" : true
}
}
},
"shifts" : {
"20191117" : {
"key1" : {
"endTime" : "00:00",
"numOfEmps" : 3,
"startTime" : "00:00",
"wage" : 0
},
"key2" : {
"endTime" : "00:00",
"numOfEmps" : 1,
"startTime" : "00:00",
"wage" : 0
}
}
},
"users" : {
"111" : {
"id" : "111",
"password" : "111"
},
"222" : {
"id" : "222",
"password" : "222"
},
"99999" : {
"id" : "99999",
"password" : "123",
}
}
}
Where a user can be assigned to several shifts and a shift can contain several users.
I'm currently trying to fetch all of the users assigned to a certain shift.
So the idea was attaching a ValueEventListener to linking/shift-assign/{shift-key}, run a loop and for every user-key , reference users/{user-key} and attach an inner ValueEventListener to read user object and add it to a userList.
Something like this :
mDatabase.child("linking/shift-assign").child(shiftKey)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for(DataSnapshot ds : dataSnapshot.getChildren()){
mDatabase.child("users").child(ds.getKey())
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot2) {
mUser user = dataSnapshot2.getValue(mUser.class);
userList.add(user);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
}
adapter = new UsersAssignedAdapter(UsersAssignedActivity.this, userList);
lv.setAdapter(adapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
I debugged it and noticed that the for loop is finished before the inner ValueEventListener is called, which is why I'm getting an empty list in my adapter. I'm guessing this is due to its asynchronous behavior.
So my question is - is there any way I can query all user ids and for each one perform another query?

Related

Firebase getChildrenCount() showing 0

I've tried everything but couldn't solve this problem.
Firebase getChildrenCount() showing 0, when I restart then Activity it showing 0.
But when I start the Activity for first time after app open it show's right data.
I tried to find log Error for onCancelled for ValueEventLisener but their is no Error.
Please help me to solve this problem.
My Code
uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
friendsRef=FirebaseDatabase.getInstance().getReference("Friends");
friendsRef.child(uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
int Friend = (int) snapshot.getChildrenCount();
friendsCountTv.setText(Integer.toString(Friend));
}else {
friendsCountTv.setText("0");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.e("ERROR/",error.getMessage());
}
});
My DataBase
"Friends" : {
"QygAGx6eszWENoVvEdaL1uEwFxW2" : {
"hLEGHsnKunew0NTqOH8dd4TnzfZ2" : "true",
"stg15QKZFhNmTCYrgL5PtQ4wxJf2" : "true"
},
"hLEGHsnKunew0NTqOH8dd4TnzfZ2" : {
"QygAGx6eszWENoVvEdaL1uEwFxW2" : "true",
"stg15QKZFhNmTCYrgL5PtQ4wxJf2" : "true"
},
"stg15QKZFhNmTCYrgL5PtQ4wxJf2" : {
"QygAGx6eszWENoVvEdaL1uEwFxW2" : "true",
"hLEGHsnKunew0NTqOH8dd4TnzfZ2" : "true"
},
}
I think there is no children in your Database Child Ref.
"stg15QKZFhNmTCYrgL5PtQ4wxJf2" : {
"QygAGx6eszWENoVvEdaL1uEwFxW2" : "true",
"hLEGHsnKunew0NTqOH8dd4TnzfZ2" : "true"
},
Maybe if the structure is like this, it is considered to be children.
"stg15QKZFhNmTCYrgL5PtQ4wxJf2" : {
"CHILD NAME" : {
"PROPERTY" : "VALUE",
},
"QygAGx6eszWENoVvEdaL1uEwFxW2" : "true",
"hLEGHsnKunew0NTqOH8dd4TnzfZ2" : "true"
},
Hope this is the issue.
If this is the case, then use snapshot.getValue().size() to retrieve the properties length.

Android Firebase Retrieving data as a list from multiple nods

I am using firebase realtime database in my first android app. I'm trying to retrieve data from firebase as an arraylist of "username" but i'm constantly having the Query returning a null result. i'm very new to firebase so i'm really struggling with data retrieval errors.
"Marchand" : {
"Taha" : {
"adress" : "58 avenu St Eugène ",
"blockage" : false,
"latitude" : 35.7498635,
"longitude" : -0.5566705,
"mail" : "mailmail#gmail.com ",
"password" : "123456",
"signalement" : 0,
"telephone" : "0666666666",
"username" : "Taha"
},
"Yasmine" : {
"adress" : "Address kkdndbdk ",
"blockage" : false,
"latitude" : 35.7498636,
"longitude" : -0.5566704,
"mail" : "randommail#gmail.com",
"password" : "bobo",
"signalement" : 0,
"telephone" : "06999999",
"username" : "Yasmine"
}
.
.
.
This is one of my attempts, i tried to use the order-by-child method to iterate through the multiple nods that i have but i'm sure that it's not the right way to do this, this gives me null poiter exceptions because the datasnapshot is returning a NULL value :
referenceMarchand = rootNode.getReference("Marchand");
final ArrayList<String> types = new ArrayList<>();
Query users = referenceMarchand.orderByChild("username");
users.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
types.add(dataSnapshot.child("username").toString());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
lets make use of some functions of firebase, Lets see it works for you.
part 1)
we will save it another way around
"Merchant" : {"Name" : "Taha"
"ID" :"-KSMCMCMnnkd"},//Firebase generated id
{"Name" : "Yasmine"
"ID" :"-KSMCMccccnkd"},//Firebase generated Id
...........
Part 2)
And Save the Details
"Details" : {
"ID" : "-KSMCMCMnnkd" //Firebase generated id
"adress" : "58 avenu St Eugène ",
"blockage" : false,
"latitude" : 35.7498635,
"longitude" : -0.5566705,
"mail" : "mailmail#gmail.com ",
"password" : "123456",
"signalement" : 0,
"telephone" : "0666666666",
"username" : "Taha"},
{
"ID":"-KSMCMccccnkd" //Firebase generated id
"adress" : "Address kkdndbdk ",
"blockage" : false,
"latitude" : 35.7498636,
"longitude" : -0.5566704,
"mail" : "randommail#gmail.com",
"password" : "bobo",
"signalement" : 0,
"telephone" : "06999999",
"username" : "Yasmine"}
In Part 1)
DatabaseRefrence ref = FirebaseDatabase.getInstance("/Path");
String id = ref.child("Merchant").push().getKey(); //Firebase generated id
Merchant merchant = new Merchant();
merchant.setId(id);
merchant.setName("SomeName");
ref.child("Merchant").child(id).setValue(merchant);
Part 2)
Detail detail = new Detail();
detail.setAddress("Some Address");
detail.setBlockage("false");
detail.setLatitude("SomeValue");
detail.setEmail("someText#gmail.com");
......
ref.child("Details").child(id).setValue(detail);
Now
List<Merchant> merchants = new ArrayList<>();
List<Detail> details = new ArrayList<>();
ref.child("Merchant").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(Datasnapshot snapshot:dataSnapshot){
Merchant merchant = snapshot.getValue(Merchant.class);
merchants.add(merchant);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
ref.child("Details").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(Datasnapshot snapshot:dataSnapshot){
Detail detail = snapshot.getValue(Detail.class);
details.add(detail);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Now you can get the details for some merchant or save it in local database for later querying.

android: adding a new node

Need to add a new node "Completed" under the parent which will eventually contain all the information from the node "Requests" at end of the ride.
So basically, I need to create node "Completed" first but its not adding it.
database
{
"Requests" : {
"iowpxU6WKUWpzWJyfssSoOVCPFj2" : {
".priority" : "f8118c3k3v",
"destination" : "221 Prince William St",
"details" : {
"driver" : "nYIAHSYimJMHbMkXqDt9PQ0U3Nf2",
"location" : "27 Horsfield St",
"request status" : "accepted",
"ridePrice" : 3.75,
"rideStatus1" : "arrived at pickup",
"rideStatus2" : "rider in vehicle",
"rideStatus3" : "destination bound",
"rideStatus4" : "arrived at destination",
"rider" : "iowpxU6WKUWpzWJyfssSoOVCPFj2",
"riderPaid" : "true"
},
"Users" : {
"Drivers" : {
"nYIAHSYimJMHbMkXqDt9PQ0U3Nf2" : {
"driver" : "nYIAHSYimJMHbMkXqDt9PQ0U3Nf2",
"email" : "driver#me.com",
"name" : "driver",
"password" : "whatever",
"phone" : "5551212",
"rates" : "0"
}
},
"Riders" : {
"iowpxU6WKUWpzWJyfssSoOVCPFj2" : {
"avatarUrl" : "",
"email" : "rider#me.com",
"name" : "rider",
"password" : "whatever",
"phone" : "5551313",
"rates" : "0",
"riderId" : "iowpxU6WKUWpzWJyfssSoOVCPFj2"
}
}
}
}
addNewNode
private void addNewNode() { // TODO: ........ NOT ADDING NEW NODE :-| ..........
Toast.makeText(this, "addNewNode", Toast.LENGTH_LONG).show();
DatabaseReference newNode = FirebaseDatabase.getInstance().getReference("Completed");
newNode.child(riderId).push().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Toast.makeText(DriverTripDetail.this, "addNewNode: onDataChange", Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Any assistance on how I can fix this would be greatly appreciated.
The Firebase Database stores values at paths. If there is no value, the path does not exist.
Your code creates a reference to /Completed/$pushID. but doesn't set any value, so the path doesn't get created. Something like this will work, since it sets a value:
newNode.child(riderId).push().setValue(true)

Get reference for my Firebase Query

I'm working using Firebase this my database is looking like
my database screenshot
{
"CookerInfo" : {
"org1mLyyJNXtiGo8NimxhWvpId42" : {
"about" : "Cooker since 2005",
"address" : "agamy - italy ",
"available" : "tuesday from 5 am to 9 pm",
"cookerDishes" : {
"-Kk3RgXiUEgpgjF1aAdc" : {
"foodName" : "mol5ia",
"foodUrl" : "https://firebasestorage.googleapis.com/v0/b/fir-auth- aa979.appspot.com/o/dishphoto%2F1494723249227.jpg?alt=media&token=0fc03b18-d310- 493a-b332-c1f3e4896567",
"price" : "8 $",
"timeToPrepared" : "10 min",
"weight" : "100 gm "
}
},
"name" : "chef.mohamed",
"phone" : "0192822228",
"url" : "https://firebasestorage.googleapis.com/v0/b/fir-auth-aa979.appspot.com/o/cookerPhoto%2F1494723157098.jpg?alt=media&token=19e4e376-0013-4410-bc04-0483aff09902"
},
"vuUscH2L7wgtj2N3rGWOOjgv23s2" : {
"about" : "cookgood",
"address" : "alexandria",
"available" : "sunday",
"cookerDishes" : {
"-Kk32fy0FO1vtZgm6AOK" : {
"foodName" : "chiken",
"foodUrl" : "https://firebasestorage.googleapis.com/v0/b/fir-auth- aa979.appspot.com/o/dishphoto%2F1494716692079.jpg?alt=media&token=a70ed96e-acbc-45c6-95b7-4811fd8e2e26",
"price" : "10$",
"timeToPrepared" : "10 min",
"weight" : "100gm"
},
"-Kk32mfQWiMRLFV2SMo7" : {
"foodName" : "rise",
"foodUrl" : "https://firebasestorage.googleapis.com/v0/b/fir-auth- aa979.appspot.com/o/dishphoto%2F1494716718899.jpg?alt=media&token=6b9007f5-c22e-4ed4-83aa-a80f45e5363f",
"price" : "8 $",
"timeToPrepared" : "8 min",
"weight" : "50 gm"
}
},
"name" : "sherbini",
"phone" : "01093812681",
"url" : "https://firebasestorage.googleapis.com/v0/b/fir-auth-aa979.appspot.com/o/cookerPhoto%2F1494716634787.jpg?alt=media&token=2ba72b6d-0af0-4235-bff5-4b706e91486f"
}
}
}
And I want to reach to cookerDishes for specific cooker only (1 cooker) to put his dishes in gridview, however I don't save the ID in model.
I tried something like that, but it didn't work.
Query queryRef=mDatabaseRef.orderByChild("name")
.equalTo(COOKERNAME);
DatabaseReference node =queryRef.getRef();
node.child("cookerDishes").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> children=dataSnapshot.getChildren();
for (DataSnapshot child : children){
FoodDish fooddish = new FoodDish();
String food_name =child.child("foodName").getValue(String.class);
fooddish.setFoodName(food_name);
foodList.add(fooddish);
}
gv.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I think you forgot to call notifyDataSetChanged() on your addapter
You don't need to call getRef() on the query. Instead you should attach the listener directly to the query:
Query queryRef=mDatabaseRef
.orderByChild("name")
.equalTo(COOKERNAME);
queryRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot cookerSnapshot : dataSnapshot.getChildren()){
DataSnapshot cookerDishes = cookerSnapshot.getChild("cookerDishes"));
for (DataSnapshot dishSnapshot: cookerDishes.getChildren()) {
FoodDish fooddish = new FoodDish();
String food_name =child.child("foodName").getValue(String.class);
fooddish.setFoodName(food_name);
foodList.add(fooddish);
}

Retrieving child's Information from Firebase back to android studio

I am new to Android Studio and Firebase itself. I understand that in order to get the child's data from its unique ID, I might need to use a Data Snapshot method. For example, I need to retrieve the name from Firebase database back to android studio application. How do I implement it in this case? Help would be much appreciated!
{
"0Zs7aiWplRRJ5IJ5pazuUOxIdqz2" : {
"name" : "yeo",
"pos" : "intern",
"team" : "nwrs"
},
"kaLCjJFoGETWCWH42kNkc90b5Ku1" : {
"2016" : {
"9" : {
"25" : {
".priority" : 0.0,
"AM" : "",
"OT" : "",
"OVN" : "",
"PM" : "",
"TPT" : ""
}
},
"10" : {
"1" : {
".priority" : 0.0,
"AM" : "zxc11",
"OT" : "12",
"OVN" : "33",
"PM" : "222",
"TPT" : "54"
},
"26" : {
"AM" : "aa",
"OVN" : "gg",
"PM" : "ccc",
"TPT" : ""
},
"29" : {
".priority" : 0.0,
"AM" : "dd",
"OVN" : "aa",
"PM" : "ss",
"TPT" : "2fd"
}
}
},
"name" : "Jing Yang",
"pos" : "Intern",
"team" : "NWRS"
}
}
Below is my current code
root.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Set<String> set = new HashSet<String>();
Iterator i = dataSnapshot.getChildren().iterator();
while (i.hasNext()){
set.add(((DataSnapshot)i.next()).getKey());
}
names.clear();
names.addAll(set);
arrayAdapter.notifyDataSetChanged();
I'll assume that root refers to the root of your database. In that case your onDataChange will get a snapshot of the entire data at that location. You can loop over them and get the properties of each child in turn with:
root.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Set<String> set = new HashSet<String>();
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
//set.add(childSnapshot.getKey());
set.add(childSnapshot.child("name").getValue(String.class));
}
names.clear();
names.addAll(set);
arrayAdapter.notifyDataSetChanged();
But I highly recommend that you create a Java class that represents the items in your list. In your case that can be as simple as:
public class Item {
public string name;
public string pos;
public string team;
}
Then you can read the items with:
root.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Set<String> set = new HashSet<String>();
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
Item child = childSnapshot.getValue(Item.class);
set.add(item.name);
}
names.clear();
names.addAll(set);
arrayAdapter.notifyDataSetChanged();

Categories

Resources