Reputation: 4412
I have successfully implemented geoFire to get the keys of entries from a main firebase node within the user's area.
I have then attempted to store those keys in a new, unique node, in order to use them later to populate a viewHolder, as this seems to be best practice.
The problem is that I don't want all of the objects stored in the unique node to actually populate the viewHolder; I only want a subset of them.
If I filter inside the populateViewHolder method, e.g.,
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
SwarmReport retrievedModel = dataSnapshot.getValue(SwarmReport.class);
if(!retrievedModel.isClaimed()){
viewHolder.bindSwarmReport(retrievedModel);
}
}
I get some items in the viewHolder that are blank.
If, instead, I try to filter before setting up the FirebaseAdapter, e.g. in my addGeoQueryEventListener methods, I have to add an addListenerForSingleValueEvent
to check the criteria by which I aim to filter:
public void onKeyEntered(String key, GeoLocation location) {
claimCheckKey = key;
final DatabaseReference claimCheckRef = FirebaseDatabase.getInstance().getReference("all").child(key);
claimCheckRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
SwarmReport claimCheckSwarmReport = dataSnapshot.getValue(SwarmReport.class);
if (!claimCheckSwarmReport.isClaimed()){
swarmReportIds.add(claimCheckKey);
}
}
It seems that onGeoQueryReady
executes before addListenerForSingleValueEvent
in onKeyEntered
is finished. Any recommendations on how to get onGeoQueryReady
to wait for all of the swarmReportIds.add(claimCheckKey)s to complete?
In case it's helpful, here's a snapshot of my firebase structure:
Upvotes: 4
Views: 455
Reputation: 91
I don't really understand what you are trying to achieve but I will take a guess and say that you want not only the closest key
but you also want to filter the closest key
based on some other criteria, e.g., closest restaurant then prices,
The workaround I did to achieve this, (still looking for better options) is to set a flag inside the onDatachange
method that I called on inside the onKeyentered
method, that compares entries inside that node, (for sake of argument we will say prices)
UPDATE
@Override
public void onKeyEntered(final String key, GeoLocation location) {
final DatabaseReference db = FirebaseDatabase.getInstance().getReference("<your ref>"+key);
db.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String dishPrice=ds.getValue(String.class);
int price=Integer.parseInt(dishPrice);
if (price<=12) {
isMatch=true;
}
}
if(isMatch){
getRestaurants(key);
}
isMatch=false;
}
And outside the for each loop of onDataChange
I set to execute the function that populates the arraylist
of my adapter
only when the function is true
getRestaurants method
private void getRestaurants(final String id) {
final DatabaseReference temp=FirebaseDatabase.getInstance().getRef("<your
ref>"+id)
temp.child(id).addListenerForSingleValueEvent(new
ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Restaurant restaurant = dataSnapshot.getValue(Restaurant.class);
restaurant.setName(restaurant.getName());
restaurant.setImageUri(restaurant.getImageUri());
restaurant.setUid(id);
//add elemens to arraylist
resList.add(restaurant);
adapter.notifyDataSetChanged();
}
Another suggestion would be to make a function on the cloud, (assuming again) in your case that all you need is to monitor whether the value of "claimed" changes, so you can set an onUpdate
event trigger or and onWrite
and check the value in onChanged()
and get the current value (true/false)after that you can make use of geoFire queries and get the close by users and update their nodes depending on the value.
Upvotes: 5