Filtering geoFire requests by specific criteria before populating viewHolder in Android
I have successfully applied geoFire to get the record keys from the main firebase node in the custom area.
Then I tried to store those keys in a new unique node so I can use them later to populate the viewHolder as this seems to be the best practice.
The problem is, I don't want all 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 for example
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
SwarmReport retrievedModel = dataSnapshot.getValue(SwarmReport.class);
if(!retrievedModel.isClaimed()){
viewHolder.bindSwarmReport(retrievedModel);
}
}
I am getting some items in the viewHolder that are empty.
If instead I try to filter before setting up the FirebaseAdapter eg. in my addGeoQueryEventListener methods, I have to add addListenerForSingleValueEvent
to check the criteria by which I want 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);
}
}
Seems to onGeoQueryReady
run before completion addListenerForSingleValueEvent
in onKeyEntered
. Any advice on how to get onGeoQueryReady
to wait for the entire swarmReportIds.add (ClaimCheckKey) command to complete?
In case it's helpful, here's a snapshot of my firebase structure:
source to share
I don't really understand what you are trying to achieve, but I'll guess and say that you not only want the closest key
, but also want to filter the closest key
based on some other criteria, like the closest restaurant, then prices.
The workaround I did for this (still looking for better options) is to set a flag inside the method onDatachange
I called inside the method onKeyentered
that compares the records inside the node, (for the sake of the argument, we'll 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 for each loop, onDatachange
I decided to execute a function that fills arraylist
mine 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 is to make a function in the cloud (assuming again) in your case that all you need is to check if the value of the "declared" changes changes, so you can set an event trigger onUpdate
or onWrite
and check the value in onChanged()
and get the current value (true / false), after which you can use geoFire requests and get closure by users and update their nodes based on the value.
source to share