Search code examples
javaandroidadapterlistadapter

Implementing Filter/Search functionality in ListAdapter returns UnsupportedOperationException


I am trying to implement search functionality in my Adapter class that extends ListAdapter. I am not using RecyclerAdapter but instead I am using ListAdapter. In main activity to for searching field I am using EditText and addTextChangedListener. I am having this exception:

exception

This is my code:

public class NoteAdapter extends ListAdapter<Note, NoteAdapter.NoteHolder> implements Filterable {
    private List<Note> mNoteListInit;
    private OnItemClickListener mListener;

    public NoteAdapter() {
        super(DIFF_CALLBACK);
        exampleListFull = new ArrayList<>(getCurrentList());
    } 

    @Override
    public Filter getFilter() {
        return exampleFilter;
    }
    
    public void setInitList(List<Note> noteList) {
        mNoteListInit = new ArrayList<>(noteList);
    }


    private Filter exampleFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            List<Note> filteredList = new ArrayList<>();

            if (constraint == null || constraint.length() == 0) {
                filteredList.addAll(mNoteListInit);
            } else {
                String filterPattern = constraint.toString().toLowerCase().trim();

                for (Note note : mNoteListInit) {
                    if (note.getTitle().toLowerCase().contains(filterPattern)) {
                        filteredList.add(note);
                    }
                }
            }
            FilterResults filterResults = new FilterResults();
            filterResults.values = filteredList;
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            submitList((List) results.values);
        }
    };

In MainActivity:

mEditTextToolbarSearch.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) { }

    @Override
    public void afterTextChanged(Editable s) {
        noteAdapter.getFilter().filter(s.toString());
    }
});

mNoteViewModel.getAllNotes().observe(this, new Observer<List<Note>>() {
    @Override
    public void onChanged(List<Note> notes) {
        noteAdapter.submitList(notes);
        noteAdapter.setInitList(noteAdapter.getCurrentList());
    }
});

Solution

  • You are getting UnsupportedOperationException Due to using .clear() on UnmodifiableCollection

    Looking into your code to see where you use clear():

    getCurrentList().clear();
    

    So, definitly getCurrentList() is UnmodifiableCollection, so you can't modify it like normal Lists.

    The documentation of getCurrentList() says:

    The returned list may not be mutated - mutations to content must be done through submitList(List).

    So, you can mutate the ListAdapter getCurrentList() through submitList

    So, try to replace getCurrentList().clear() with submitList(new ArrayList())