Atticus29
Atticus29

Reputation: 4412

Filter geoFire queries by certain criteria before populating viewHolder in Android

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: enter image description here

Upvotes: 4

Views: 455

Answers (1)

omar A.R
omar A.R

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 onUpdateevent 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.

Event Triggers

Cloud Functions

Upvotes: 5

Related Questions