Search code examples
javaandroidlistviewfirebase-realtime-databasesearchview

Search data from Firebase using Listview in Android


I got an Firebase database which are able to show data in a listview. All of the data are contained into objects, which got data in it. I want to be able to write example "Lars" into the search bar, and then it has to update the listview to only contain those objects that contain that string, and if I delete everything from the search bar, it should show everything again. The first for loop works, and the second for loop are my attempt to search the data. My Firebase structure looks like this :enter image description here

    private DatabaseReference mDatabaseReference;
    private ListView mUserList;
    private SearchView searchModule;

    private ArrayList<String> mUsernames = new ArrayList<>();
    private ArrayList<String> filteredUsernames = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_existing_customer);

        mDatabaseReference = FirebaseDatabase.getInstance().getReference("Buyers");

        mUserList = (ListView) findViewById(R.id.UserListView);


        searchModule = (SearchView)  findViewById(R.id.SearchTab);

        final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mUsernames);

        final ArrayAdapter<String> filteredArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, filteredUsernames);

        mUserList.setAdapter(arrayAdapter);

        mDatabaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {

                    Map<String, String> map = (Map<String, String>) childSnapshot.getValue();
                    Log.v("YourValue,","Map value is:" +map.toString());
                    Log.d("TAG", "onChildAdded:" + dataSnapshot.getKey());
                    Buyers buyerList = new Buyers(map);
                    mUsernames.add(buyerList.getData());
                }
                CharSequence searchValue = (CharSequence) searchModule;
                arrayAdapter.getFilter().filter(searchValue);

                arrayAdapter.notifyDataSetChanged();
            }


            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

    }

Solution

  • Three things:

    1. You don't add any data to filteredUsernames. Just like you do to mUsernames, you should add the data to filteredUsernames.
    2. getFilter is a method of ArrayAdapter, you should use it on filteredArrayAdapter
    3. You can use a listener to listen any changes on the query and apply a filter

      for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
          Map<String, String> map = (Map<String, String>) childSnapshot.getValue();
          Buyers buyerList = new Buyers(map);
          filteredUsernames.add(buyerList.getData());
      }
      
       searchModule.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
          @Override
          public boolean onQueryTextSubmit(String query) {
              return false;
          }
      
          @Override
          public boolean onQueryTextChange(String newText) {
              filteredArrayAdapter.getFilter().filter(newText);
              filteredArrayAdapter.notifyDataSetChanged();
              return true;
          }
      });
      

    This is more or less how it should look. However, since the filter is applied to the adapter, you can notice that filteredUserNames and mUsernames are same, so you don't actually need two lists. Alternatively, if you need the filters, you can also do the filtering manually with an if statement and a contains check.