1

I have a RecyclerView populated by a RoomDatabase and created a SearchView to filter the results if I want to extract a specific set of values from there. The issues are as follows:

  • The list gets populated only after I click on the search button, not when the view is opened.
  • When using the search bar, whatever I write, as long as it is an element from the list, it only shows the element on the first position. If I type something that is not part of the list, it shows the list blank, so this works at least.

This is the code for the Adapter:

 public class AbonamenteAdapter2 extends RecyclerView.Adapter<AbonamenteAdapter2.AbonamenteHolder2> implements Filterable {

    private List<Abonamente> abonamente;
    private List<Abonamente> abonamenteFiltered;
   private OnItemClickClickListener listener;

    public void setAbonamente(final List<Abonamente> abonamente) {
        //this.context = (Context) context;
        if (this.abonamente == null) {
            this.abonamente = abonamente;
            this.abonamenteFiltered = abonamente;
            notifyItemChanged(0, abonamenteFiltered.size());
        } else {
            final DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
                @Override
                public int getOldListSize() {
                    return AbonamenteAdapter2.this.abonamente.size();
                }

                @Override
                public int getNewListSize() {
                    return abonamente.size();
                }

                @Override
                public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
                    return AbonamenteAdapter2.this.abonamente.get(oldItemPosition).getTreatPicked() ==
                            abonamente.get(newItemPosition).getTreatPicked();
                }

                @Override
                public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {

                    Abonamente newAbonament = AbonamenteAdapter2.this.abonamente.get(oldItemPosition);
                    Abonamente oldAbonament = abonamente.get(newItemPosition);

                    return newAbonament.getTreatPicked() == oldAbonament.getTreatPicked();
                }
            });
            this.abonamente = abonamente;
            this.abonamenteFiltered = abonamente;
            result.dispatchUpdatesTo(this);
        }
    }

    @NonNull
    @Override
    public AbonamenteHolder2 onCreateViewHolder (@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);
        return new AbonamenteHolder2(view);
    }

    @Override
    public void onBindViewHolder(@NonNull AbonamenteHolder2 holder2, int position) {
        Abonamente currentAb = abonamente.get(position);
        holder2.treatChosen.setText(currentAb.getTreatPicked());

        //holder2.treatChosen.setText(abonamente.get(position).getTreatPicked());
        //holder2.treatDisplay = abonamente.getTreatDisplay();
        //holder2.treatPrice = abonamente.getPrice();
    }

    @Override
    public int getItemCount() {
        if(abonamente != null) {
            return abonamenteFiltered.size();
        } else {
            return 0;
        }
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String charString = charSequence.toString();
                if (charString.isEmpty()) {
                    abonamenteFiltered = abonamente;
                } else {
                    List<Abonamente> filteredList = new ArrayList<>();
                    for (Abonamente abonament : abonamente) {
                        if (abonament.getTreatPicked().toLowerCase()
                                .contains(charString.toLowerCase())) {
                            filteredList.add(abonament);
                        }
                    }
                    abonamenteFiltered = filteredList;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = abonamenteFiltered;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                abonamenteFiltered = (ArrayList<Abonamente>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }


    public class AbonamenteHolder2 extends RecyclerView.ViewHolder {
        TextView treatChosen;


        public AbonamenteHolder2(View view) {
            super(view);
            treatChosen = view.findViewById(R.id.element);
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int position = getAdapterPosition();
                    if(listener != null && position != RecyclerView.NO_POSITION) {
                        listener.onItemClick(abonamente.get(position));
                    }
                }
            });
        }
    }

    public interface OnItemClickClickListener {
        void onItemClick(Abonamente abonamente);
    }

    public void setOnItemClickListener(OnItemClickClickListener listener) {
        this.listener = listener;
    }
}

And this is the code for the activity with the list and search bar. It is triggered by a button press from a different activity:

public class RecyclerList extends AppCompatActivity {

    public static final int GET_DATA_LIST = 1;

    private SearchView searchView;
    private AbonamenteAdapter2 adapter;

    private AbonamenteViewModel viewModel;
    private String treatDisplay;
    private int treatPrice;

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

        RecyclerView recyclerView = findViewById(R.id.list);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);

        adapter = new AbonamenteAdapter2();
        recyclerView.setAdapter(adapter);

        viewModel = ViewModelProviders.of(this).get(AbonamenteViewModel.class);
        viewModel.getAllEntries().observe(this, new Observer<List<Abonamente>>() {
            @Override
            public void onChanged(@Nullable List<Abonamente> abonamentes) {
                adapter.setAbonamente(abonamentes);
            }
        });

        adapter.setOnItemClickListener(new AbonamenteAdapter2.OnItemClickClickListener() {
            @Override
            public void onItemClick(Abonamente abonamente) {
                Intent intent = new Intent(RecyclerList.this, MainActivity.class);
                intent.putExtra(MainActivity.EXTRA_ID, abonamente.getId());
                intent.putExtra(MainActivity.EXTRA_CHOICE, abonamente.getTreatPicked());
                intent.putExtra(MainActivity.EXTRA_TREAT, abonamente.getTreatDisplay());
                intent.putExtra(MainActivity.EXTRA_PRICE, abonamente.getPrice());
                startActivityForResult(intent, GET_DATA_LIST);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_bar, menu);

        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        searchView = (SearchView) menu.findItem(R.id.action_search)
                .getActionView();
        searchView.setSearchableInfo(searchManager
                .getSearchableInfo(getComponentName()));
        searchView.setMaxWidth(Integer.MAX_VALUE);

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit (String query) {
                adapter.getFilter().filter(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String query) {
                adapter.getFilter().filter(query);
                return false;
            }
        });
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_search) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        if(!searchView.isIconified()) {
            searchView.setIconified(true);
            return;
        }
        super.onBackPressed();
    }
}

I went through the code up and down quite a lot of time and can't seem to figure out what the issue is.

5
  • 1
    why are you just notifying the first index change? notifyItemChanged(0, abonamenteFiltered.size()); ??!!
    – Mohammed
    Commented Dec 5, 2018 at 13:06
  • Changed notifyItemChanged to notifyDataSetChanged() and the list loads when the activity opens. But I still have issues with the filtering.
    – Andy Gix
    Commented Dec 5, 2018 at 13:31
  • it's better to have just one list in your adapter, and just follow these steps everytime you want to apply a filter: list.clear() -> list.add(filteredItems) -> notifyDataSetChanged()
    – Mohammed
    Commented Dec 5, 2018 at 14:32
  • I presume there isn't a chat here. I have taken the Filter part from a tutorial and adapted it to my own code. But I am not sure how to adapt what you mentioned above.
    – Andy Gix
    Commented Dec 5, 2018 at 15:18
  • Okay, I'll share an answer here, implementing what you need on filtering, etc.
    – Mohammed
    Commented Dec 5, 2018 at 15:28

1 Answer 1

3

This may be comment for your question but here because of low reputation i need to write answer. onBindViewHolder method you need to set your filtered list to your Model.

Use

Abonamente currentAb = abonamenteFiltered .get(position);

Instead of

Abonamente currentAb = abonamente.get(position);
1
  • Perfect! Thanks, Ashwin.
    – LineDrop
    Commented May 27, 2021 at 16:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.