2

I have a SearchView in a custom toolbar that should filter the adapter, but the adapter does not update after I call notifyDataSetChanged()

My Adapter class (the relevant bits):

public class RaffleAdapter extends ArrayAdapter<Raffle> implements Filterable {

    private int mLayoutResourceID;
    private final SQLiteDatabase mDB;
    private Context mContext;
    private RaffleAdapter adapter = this;
    private ArrayList<Raffle> raffles, rafflesFiltered;
    RaffleFilter raffleFilter;

    public RaffleAdapter(Context context, int resource, ArrayList<Raffle> raffles, SQLiteDatabase db) {
        super(context, resource, raffles); 
        this.mLayoutResourceID = resource;
        this.mDB = db;
        this.mContext = context;
        this.raffles = raffles;
        this.rafflesFiltered = new ArrayList<>(raffles);
    }
    @Override
    public Filter getFilter() {
        if (raffleFilter == null) {
            raffleFilter = new RaffleFilter();
        }
        return raffleFilter;
    }

    class RaffleFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            if (constraint != null && constraint.length() > 0) {
                constraint = constraint.toString().toUpperCase();
                ArrayList<Raffle> filters = new ArrayList<>();

                for (int i = 0; i < rafflesFiltered.size(); i++) {
                    if (rafflesFiltered.get(i).getRaffleName().toUpperCase().contains(constraint)) {
                        Raffle raffle = rafflesFiltered.get(i);
                        filters.add(raffle);
                    }
                }
                results.count = filters.size();
                results.values = filters;
            } else {
                results.count = rafflesFiltered.size();
                results.values = rafflesFiltered;
            }
            return results;
        }
        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            raffles = (ArrayList<Raffle>)filterResults.values;
            notifyDataSetChanged();
        }
    }
}

My main activity class (the relevant bits):

public class MainActivity extends AppCompatActivity {

    RaffleAdapter raffleListAdapter;

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

        final ListView myList = findViewById(R.id.myList);
        final ArrayList<Raffle> raffles = RaffleTable.selectAll(db);

        raffleListAdapter = new RaffleAdapter(MainActivity.this, R.layout.raffle_display, raffles, db);
        myList.setAdapter(raffleListAdapter);
    } 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        MenuItem mSearch = menu.findItem(R.id.search);
        SearchView mSearchView = (SearchView) mSearch.getActionView();
        mSearchView.setQueryHint("Search");
        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }
            @Override
            public boolean onQueryTextChange(String newText) {
                raffleListAdapter.getFilter().filter(newText);
                return true;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }
}

I know that the line raffles = (ArrayList<Raffle>)filterResults.values; in publishResults() returns the correct information, the problem is the line right after that, calling notifyDataSetChanged() doesn't seem to have any affect.

John
  • 59
  • 1
  • 6
  • 1
    Your `Adapter` isn't displaying your `rafflesFiltered` `List`. It's dislaying `ArrayAdapter`'s own internal `List` filtered from a copy of the `List` you passed in the `super` constructor call. If you need a custom `Filter`, you should instead extend `BaseAdapter`, so that you don't get your stuff mixed up with `ArrayAdapter`'s internals. If you don't really need the custom `Filter`, you should let `ArrayAdapter` handle it all, rather than trying to override its filtering. I describe `ArrayAdapter`'s built-in filtering algorithm in [my answer here](https://stackoverflow.com/a/53242503). – Mike M. May 25 '20 at 04:38
  • 1
    Fantastic, amazing how much I had over complicated things, all I had to do was add a toString to my raffle class and then remove the RaffleFilter class and getFilter override, and it worked. Thanks bro – John May 25 '20 at 05:19

0 Answers0