Search code examples
javaandroidfirebasefirebase-realtime-databaseandroid-filterable

How to filter firebase realtime database results by using Filterable class


I am looking for something like that

ArrayList<Model> models = new ArrayList();

mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
@Override
public boolena onQueryTextSubmit(String str){

    mDbReference.child("mp_path").addChildEventListener(new ChildEventListener(){
        @Override 
        public void onChildAdded(DataSnapshot ds){
             Model model = ds.getValue(Model.class);
             models.add(model);
             mAdapter.notifyDataSetChanged();
             mAdapter.getFilter().filter(str.toLowerCase());
        }

        Other methods...

    });



}

@Override
public boolean onQueryTextChanged(String str){
return false;
}

});

I have values on database

-users
    -user1
         -name: "example"
         -surname: "example"
    -user2
    -user3 ...

A user of the app will encounter with an empty screen. Then he/she will hit the search button, write a string, and submit the query. When he/she pressed enter to search it, the codes above will work and the program will retrieve all users from database. After retrieving, some method for filtering will be run (Eg. If the customer search for userx, display userx & user(x-1) & user(x+1).) Eliminating should work after retrieving data.

The problem here is whenever addChildEventListener method works, it iterates the codes inside onChildAdded method. The issue arise from firebase database being asynchronous. I want to filter results after each value is added to my models' list. Unfortunately, if i write filter method outside of database method, the program do not wait until firebase method is done and app crashes. I don't want to use firebase query methods because i use multiple and complicated filters. I searched on the net for a solution, but I could not find something to solve my problem.


Solution

  • You should use addListenerForSingleValueEvent. Not addChildEventListener.

        mDbReference.child("mp_path").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                models.clear();
                for(DataSnapshot ds : dataSnapshot.getChildren()) {
                    Model model = ds.getValue(Model.class);
                    models.add(model);
                }
                mAdapter.notifyDataSetChanged();
                mAdapter.getFilter().filter(str.toLowerCase());
            }
    
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
    
            }
        });